  /**
 * (./) OpenCV.java, v2.0 - 20/03/09
 * (by) Douglas Edric Stanley & Cousot Stéphane
 * (cc) some right reserved
 *
 * Part of the Processing Libraries project, for the Atelier Hypermedia, art 
 * school of Aix-en-Provence, and for the Processing community of course.
 *
 * -› http://ubaa.net/shared/processing/
 * -› http://hypermedia.loeil.org/processing/
 * -› http://www.processing.org/
 *
 *
 * THIS LIBRARY IS RELEASED UNDER A CREATIVE COMMONS ATTRIBUTION 3.0 LICENSE
 * › http://creativecommons.org/licenses/by/3.0/
 */




// package name
package hypermedia.video;


import processing.core.PApplet;
import processing.core.PImage;
import java.awt.Rectangle;
import java.io.File;



// all right, AWT packages are no longer imported by default in Processing 1.1
// For people who are not familary with Processing and Java, we could create a simple object 
// Rectangle here or in another package to store properties, but Java Rectangle class is more
// complex and useful than a simple storage.
//class Rectangle extends java.awt.Rectangle {}
//class Rectangle extends java.awt.geom.Rectangle2D.Float {}




/**
 * The main object for all computer vision processes.
 * 
 * <div class="hide">
 * <p>
 * To use OpenCV library in a PApplet directly in pure Java, start with this small integration sample
 * <br />for more details about Processing see the <a href="http://processing.org/">home page</a>
 * </p>
 * <pre>
 *
 *	import processing.core.*;
 *	import hypermedia.video.OpenCV;
 *
 *	public class OpenCV_PApplet extends PApplet {
 *
 *		OpenCV cv = null;  // OpenCV object
 *
 *		// Initialise Objects
 *		public void setup() {
 *		    size( 640, 480 );              // set frame size
 *		    cv = new OpenCV( this );       // link OpenCV process to this PApplet
 *		    cv.capture( width, height );   // start video stream
 *		}
 *
 *		// Display the input camera stream in frame
 *		public void draw() {
 *		    cv.read();
 *		    image( cv.image(), 0, 0 );
 *		}
 *
 *		// Call the PApplet main method
 *		public static void main( String[] args ) {
 *		    PApplet.main( new String[]{"OpenCV_PApplet"} );
 *		} 
 *	}
 *
 * </pre>
 * </div>
 *
 * @author Douglas Edric Stanley - http://www.abstractmachine.net/
 * @author Cousot Stéphane  stef[at]ubaa.net
 * @version 0.2 18/12/07
 * 
 * @see <a href="http://dev.processing.org/reference/core/javadoc/processing/core/PApplet.html">
 * processing.core.PApplet</a>
 * @usage Application
 */
public class OpenCV {
	
	
	
	/**
	 * Processing library version
	 */
	public final static String VERSION	= "2.0b4";
	
	/**
	 * C++ libraries version
	 */
	public static String CV_VERSION;
	
	
	
	/**
	 * Type of Image
	 * @see #image(int)
	 * @see #remember(int)
	 */
	public final static int SOURCE	= 0;
	public final static int BUFFER	= 1;
	public final static int MEMORY	= 2;
	//public final static int ROI		= 3;
	
	
	
	/**
	 * Colorspace of image
	 * @see #convert(int)
	 */
	public final static int RGB  = 1;
	public final static int GRAY = 12;
	public final static int HSV  = PApplet.HSB;
	
	
	public static final int ADAPTIVE_THRESH_MEAN = 0;
	public static final int ADAPTIVE_THRESH_GAUSSIAN = 1;
	
	
	/**
	 * Thresholding method
	 * @see #threshold( float )
	 * @see #threshold( float, float, int )
	 */
	public final static int THRESH_BINARY		= 0; // dst(x,y) = src(x,y) > value ? max : 0
	public final static int THRESH_BINARY_INV	= 1; // dst(x,y) = src(x,y) > value ? 0 : max
	public final static int THRESH_TRUNC		= 2; // dst(x,y) = src(x,y) > value ? value : src(x,y)
	public final static int THRESH_TOZERO		= 3; // dst(x,y) = src(x,y) > value ? src(x,y) : 0
	public final static int THRESH_TOZERO_INV	= 4; // dst(x,y) = src(x,y) > value ? 0 : src(x,y)
	public final static int THRESH_OTSU			= 8;
	
	
	
	/**
	 * Flip mode
	 * @see #flip( int )
	 * @see #remember( int, int )
	 */
	public final static int FLIP_VERTICAL	= 0;
	public final static int FLIP_HORIZONTAL = 1;
	public final static int FLIP_BOTH		= -1;
	public final static int FLIP_NONE		= -2;
	
	
	
	/**
	 * Interpolation method
	 * @see #interpolation( int )
	 */
	public final static int INTER_NN	 = 0; // nearest-neighbor (preserve hard eges)s
	public final static int INTER_LINEAR = 1; // bilinear interpolation
	public final static int INTER_CUBIC	 = 2; // bicubic interpolation (best for smooth gradients)
	public final static int INTER_AREA	 = 3; // resampling using pixel area relation.
	
	
	
	/**
	 * The maximum number of contour points available to blob detection (by default)
	 * @see #blobs( int, int, int, boolean )
	 * @see #blobs( int, int, int, boolean, int )
	 */
	public final static int MAX_VERTICES = 1024;
	
	
	
	/**
	 * Blur method
	 * @see #blur(int, int)
	 * @see #blur(int, int, int, float, float)
	 */
	//public final static int BLUR_NO_SCALE	= 0;
	public final static int BLUR			= 1;
	public final static int GAUSSIAN		= 2;
	public final static int MEDIAN			= 3;
	public final static int BILATERAL		= 4; // is a simple, non-iterative scheme for edge-preserving smoothing.
	
	
	/**
	 * Movie info selector
	 * @see #info(int)
	 * @see #jump(float, int)
	 */
	public final static int MOVIE_MILLISECONDS	= 0;
	public final static int MOVIE_FRAMES		= 1;
	public final static int MOVIE_RATIO			= 2;
	public final static int MOVIE_WIDTH			= 3;
	public final static int MOVIE_HEIGHT		= 4;
	public final static int MOVIE_FPS			= 5;
	//public final static int MOVIE_FOURCC		= 6;
	public final static int MOVIE_FRAME_COUNT	= 7;
	public final static int MOVIE_FORMAT		= 8;
	public final static int MOVIE_MODE			= 9;
	public final static int MOVIE_BRIGHTNESS    = 10;
	public final static int MOVIE_CONTRAST      = 11;
	public final static int MOVIE_SATURATION    = 12;
	public final static int MOVIE_HUE           = 13;
	public final static int MOVIE_GAIN          = 14;
	public final static int MOVIE_CONVERT_RGB   = 15;
	
	
	/** 
	 * Haar classifier flag
	 * @see #detect(float, int, int, int, int)
	 */
	public final static int HAAR_DO_CANNY_PRUNING	 = 1;
	public final static int HAAR_SCALE_IMAGE		 = 2;
	public final static int HAAR_FIND_BIGGEST_OBJECT = 4;
	public final static int HAAR_DO_ROUGH_SEARCH	 = 8;
	
	
	
	/**
	 * Standard Haar classifier cascade file used for object detection
	 * @see #cascade(String)
	 */
	public final static String CASCADE_FRONTALFACE_ALT_TREE	= "haarcascade_frontalface_alt_tree.xml";
	public final static String CASCADE_FRONTALFACE_ALT		= "haarcascade_frontalface_alt.xml";
	public final static String CASCADE_FRONTALFACE_ALT2		= "haarcascade_frontalface_alt2.xml";
	public final static String CASCADE_FRONTALFACE_DEFAULT	= "haarcascade_frontalface_default.xml";
	public final static String CASCADE_PROFILEFACE			= "haarcascade_profileface.xml";
	public final static String CASCADE_FULLBODY				= "haarcascade_fullbody.xml";
	public final static String CASCADE_LOWERBODY			= "haarcascade_lowerbody.xml";
	public final static String CASCADE_UPPERBODY			= "haarcascade_upperbody.xml";
	
	
	
	/** the Processng applet */
	protected PApplet parent = null;
	
	
	/** 
	 * OpenCV image/buffer width
	 * @see #height
	 */
	public int width	= 0;
	
	/**
	 * OpenCV image/buffer height
	 * @see #width
	 */
	public int height	= 0;
	
	/** storage variable for the brightnessContrast() method */
	private int brightness	= 0;
	private int contrast	= 0;
	
	/**
	 * The user plateform name
	 */
	public static String OS   = System.getProperty("os.name").toLowerCase();
	public static String ARCH = System.getProperty("sun.arch.data.model");
	
	
	
	
	private static int toInt( byte upper, byte lower ) {
        int ret =  upper << 8;
        ret |= lower;
        return ret;
    }
	
	

		
		
	/**
	 * Load Java/native library and 
	 * attempts to figure out problems on error
	 */
	static
    {
	
		try { 
			
			// load library dependencies
			if ( OS.indexOf("mac")!=-1 ) {
				System.loadLibrary("tbb");
				System.loadLibrary("opencv");
			}
			else {//if ( OS.indexOf("windows")!=-1 ) {
				System.loadLibrary( "tbb" );
				System.loadLibrary( "opencv"+ARCH );
			}
			
			CV_VERSION = "2";//version();
			
			System.out.println( "\n\nYOU ARE RUNNING THE PROCESSING OPENCV LIBRARY PRE-RELEASED VERSION "+VERSION );
			System.out.println( "BUILDED WITH THE C++ LIBRARY VERSION "+CV_VERSION );
			System.out.println( "CHECK FOR UPDATE @ http://ubaa.net/shared/processing/opencv\n\n" );
		}
		catch( UnsatisfiedLinkError e ) {
			System.err.println( "!!! ERROR WHILE LOADING OPENCV NATIVE LIBRARY : " + e.getMessage() + "\n" );
		}
		catch( UnsupportedClassVersionError e ) {
			/*
				compare version
			 
				 major  minor Java version 
				 45       3      1.0
				 45       3      1.1
				 46       0      1.2
				 47       0      1.3
				 48       0      1.4
				 49       0      1.5
				 50       0      1.6
			 */
			try {
				
				ClassLoader loader = OpenCV.class.getClassLoader();
				java.io.InputStream in = loader.getResourceAsStream("hypermedia/video/OpenCV.class");
				byte[] buffer = new byte[8];
				
				in.read(buffer);
				in.close();
				int minor = toInt(buffer[4], buffer[5]);
				int major = toInt(buffer[6], buffer[7]);
				System.out.println( "Java version:"+System.getProperty("java.version") );
				System.out.println( "Java class version:"+System.getProperty("java.class.version") );
				System.out.println( "Required class version:"+major+"."+minor );
				
			}
			catch( java.io.IOException ioe ) { System.out.println( ioe ); }
		}
	}
	
	
	
	
	/**
	 * Create a new OpenCV object and initialize C++ object.
	 *
	 * @see #OpenCV( PApplet )
	 * @invisible
	 */
	public OpenCV() { this(null); }
	
	
	
	/**
	 * Create a new OpenCV object embed in Processing PApplet
	 * and initialize C++ object.
	 *
	 * @param parent	the Processing PApplet object (typically use "this")
	 */
	public OpenCV( PApplet parent ) { this(parent,true); }
	
	
	/**
	 * Create a new OpenCV object and initialize C++ object if specified
	 *
	 * @param parent	the Processing PApplet object (typically use "this")
	 * @param init		create C++ object
	 */
	protected OpenCV( PApplet parent, boolean init ) {
		
		this.parent = parent;
	
		// update paths and register this object to the PApplet, 
		// while this library is used with Processing
		try {
			if ( parent instanceof PApplet )
				((PApplet)parent).registerDispose( this );
		}
		catch( NoClassDefFoundError e ) {;}
		
		// create C++ object
		if ( init )	instantiate();
	}
	
	/**
	 * Returns used C++ libraries version.
	 *
	 * @return String
	 */
	private static native String version();
	
	
	/** 
	 * Forget all OpenCV resources and free memory.
	 * This method is automatically called by Processing when the PApplet shuts down.
	 *
	 * @see #stop()
	 * @invisible
	 */
	public native void dispose();
	
	
	
	/**
	 * Stop OpenCV process.
	 *
	 * @usage	Application
	 */
	public void close() { dispose(); }
	
	
	/**
	 * Ceate an initilize a new C++ object
	 */
	private native void instantiate();
	
	
	/**
	 * Allocate required buffer with the given size and the default RGB color space.
	 * <p>This method allows you to create your own (blank) image buffer to work on.</p>
	 * <p>Except for creating an empty buffer, this method should not be directly used.<br />
	 * <code>capture()</code>, <code>movie()</code> and <code>loadImage()</code> methods will 
	 * automatically re-allocate the current buffer.<p>
	 *
	 * @param width		the buffer width
	 * @param height	the buffer height
	 *
	 * @see #capture( int, int )
	 * @see #movie( String )
	 * @see #loadImage( String )
	 
	 * @see #copy(PImage)
	 * @see #copy(String)
	 * @see #copy(PImage, int, int, int, int, int, int, int, int)
	 * @see #copy(String, int, int, int, int, int, int, int, int)
	 * @see #copy(int[], int, int, int, int, int, int, int, int, int)
	 *
	 * @example copy
	 */
	public void allocate( int width, int height ) {
		allocate( width, height, RGB );
	}
	
	/**
	 * Allocate required buffer with the given size and the specified color space.
	 * <p>This method allows you to create your own (blank) image buffer to work on.</p>
	 * <p>Except for creating an empty buffer, this method should not be directly used.<br />
	 * <code>capture()</code>, <code>movie()</code> and <code>loadImage()</code> methods will 
	 * automatically re-allocate the current buffer.<p>
	 *
	 * @param width		the buffer width
	 * @param height	the buffer height
	 * @param mode		buffer color space: RGB or GRAY
	 *
	 * @see #capture( int, int )
	 * @see #movie( String )
	 * @see #loadImage( String )
	 
	 * @see #copy(PImage)
	 * @see #copy(String)
	 * @see #copy(PImage, int, int, int, int, int, int, int, int)
	 * @see #copy(String, int, int, int, int, int, int, int, int)
	 * @see #copy(int[], int, int, int, int, int, int, int, int, int)
	 *
	 * @example copy
	 */
	public native void allocate( int width, int height, int mode );
	
	
	
	public void draw() {
		draw( 0, 0 );
	}
	public void draw( float x, float y ) {
		draw( x, y, BUFFER );
	}
	public native void draw( float x, float y, int kind );
	
	
	/**
	 * Place the image source in memory.
	 * Used by <code>absDiff()</code> to compare two images (for background extraction, for example).
	 *
	 * @description Place the image (original or current) in memory.
	 * If specified, flip the stored image around the given axis. 
	 * Used by <code>absDiff()</code> to compare two images (for background extraction, for example).
	 *
	 * @see #remember( int, int )
	 * @see #remember( int )
	 * @see #absDiff()
	 *
	 * @example absDiff
	 */
	public void remember() {
		remember( SOURCE, FLIP_BOTH-1 );
	}
	
	/**
	 * Place the specified image in memory.
	 * Used by <code>absDiff()</code> to compare two images (for background extraction, for example).
	 *
	 * @param type	which image to be stored: SOURCE or BUFFER
	 *
	 * @see #remember( int, int )
	 * @see #remember()
	 * @see #absDiff()
	 *
	 */
	public void remember( int type ) {
		remember( type, FLIP_BOTH-1 );
	}
	
	/**
	 * Place the specified image in memory and flip the stored image around the given axis.
	 * Used by <code>absDiff()</code> to compare two images (for background extraction, for example).
	 *
	 * @param type	which image to be stored: SOURCE or BUFFER
	 * @param mode	the used axis: FLIP_HORIZONTAL, FLIP_VERTICAL or FLIP_BOTH
	 *
	 * @see #remember( int, int )
	 * @see #flip( int )
	 * @see #absDiff()
	 */
	public native void remember( int type, int mode );
	
	
	
	/**
	 * Convert the current image from one colorspace to another.
	 *
	 * @param type	the target color space : RGB, GRAY
	 */
	public native void convert( int type );
	
	
	/**
	 * Calculate the absolute difference between the image in memory and the current image.
	 *
	 * @see #remember()
	 * @see #remember( int )
	 * @see #remember( int, int )
	 */
	public native void absDiff();
	
	
	/**
	 * Flip the current image around horizontal axes.
	 */
	public void flip() {
		flip( OpenCV.FLIP_HORIZONTAL );
	}
	
	/**
	 * Flip the current image around vertical, horizontal or both axes.
	 *
	 * @param mode	the used axis, FLIP_HORIZONTAL, FLIP_VERTICAL or FLIP_BOTH
	 */
	public native void flip( int mode );
	
	
	/**
	 * Apply fixed-level threshold to the current image.
	 *
	 * <p>This method applies fixed-level thresholding to single-channel array. It is typically used
	 * to get bi-level (binary) image out of grayscale image or for removing a noise (filtering out
	 * pixels with too small or too large values).</p>
	 * <p>About types of thresholding</p>
	 * <ul>
	 *		<li>THRESH_BINARY		: dst(x,y) = src(x,y) > value ? max : 0</li> (by default)
	 *		<li>THRESH_BINARY_INV	: dst(x,y) = src(x,y) > value ? 0 : max</li>
	 *		<li>THRESH_TRUNC		: dst(x,y) = src(x,y) > value ? value : src(x,y)</li>
	 *		<li>THRESH_TOZERO		: dst(x,y) = src(x,y) > value ? src(x,y) : 0</li>
	 *		<li>THRESH_TOZERO_INV	: dst(x,y) = src(x,y) > value ? 0 : src(x,y)</li>
	 *		<li>THRESH_OTSU			: Use Otsu algorithm to choose the optimal threshold value,
	 * combine the flag with one of the above THRESH_* values</li>
	 * </ul>
	 *
	 * @param value	threshold value
	 * @param max	the maximum value to use with THRESH_BINARY and THRESH_BINARY_INV thresholding types.
	 * @param type	Types of thresholding
	 *
	 * @see #threshold( float )
	 */
	public native void threshold( float value, float max, int type );
	
	/**
	 * Applies fixed-level threshold to the current image using the THRESH_BINARY thresholding type
	 * and 255 as the maximum value.
	 *
	 * @param value	threshold value
	 *
	 * @see #threshold( float, float, int )
	 */
	public void threshold( float value ) {
		threshold( value, 255, THRESH_BINARY );
	}
	
	/**
	 * Applies adaptive-level threshold to the current image using the ADAPTIVE_THRESH_MEAN thresholding type
	 * with block_size 3, and param1 5.
	 *
	 * @param max	threshold max value
	 *
	 * @see #adaptiveThreshold(float, int, int, int, int)
	 */
	public void adaptiveThreshold( float max ) {
		adaptiveThreshold(max, ADAPTIVE_THRESH_MEAN, THRESH_BINARY, 3, 5.0F);
	}

	/**
	 * Apply adaptive-level threshold to the current image.
	 *
	 * <p>This method applies adaptive-level thresholding to single-channel array.</p>
	 * <p>About method:</p>
	 * <ul>
	 * 		<li>ADAPTIVE_THRESH_MEAN - it is the mean of a "block_size X block_size" pixel neighborhood, minus param1</li>
	 * 		<li>ADAPTIVE_THRESH_GAUSSIAN - it is the weighted sum (gaussian) of a "block_size X block_size" pixel neighborhood, minus param1</li>
	 * </ul>
	 * <p>About types of thresholding:</p>
	 * <ul>
	 *		<li>THRESH_BINARY		: dst(x,y) = src(x,y) > value ? max : 0</li>
	 *		<li>THRESH_BINARY_INV	: dst(x,y) = src(x,y) > value ? 0 : max</li>
	 * </ul>
	 * <p>blockSize – The size of a pixel neighborhood that is used to calculate a threshold value for the pixel: 3, 5, 7, etc</p>
	 *
	 * @param max	 the maximum value to use with THRESH_BINARY and THRESH_BINARY_INV thresholding types.
	 * @param method the adaptive method type MEAN or GAUSSIAN
	 * @param type	 Types of thresholding
	 * @param blockSize the block size to perform on
	 * @param param1 the constant to subtract from the mean
	 *
	 * @see #adaptiveThreshold(float)
	 */
	public native void adaptiveThreshold( float max, int method, int type, int blockSize, float param1 );
	
	
	/**
	 * Adjust the image brightness with the specified value (in range of -128 to 128).
	 *
	 * @param value	the new brightness value
	 *
	 * @see #contrast( int )
	 * @example	brightcont
	 */
	public void brightness( int value ) {
		brightness = Math.min( 128, Math.max(value,-128) );
		brightnessContrast( brightness, contrast );
	}
	
	/**
	 * Adjust the image contrast with the specified value (in range of -128 to 128).
	 *
	 * @param value		the new contrast value
	 *
	 * @see #brightness( int )
	 * @example	brightcont
	 */
	public void contrast( int value ) {
		contrast = Math.min( 128, Math.max(value,-128) );
		brightnessContrast( brightness, contrast );
	}
	
	/**
	 * Adjust both image contrast and brightness with the passed values. 
	 *
	 * @param brightness	the new brightness value
	 * @param contrast		the new contrast value
	 *
	 * @see #brightness( int )
	 * @see #contrast( int )
	 * @invisible
	 */
	private native void brightnessContrast( int brightness, int contrast );
	
	/**
	 * Invert image.
	 */
	public native void invert();
	
	//public native void perspective();
	
	
	/**
	 * Smooth the image in one of several ways.
	 * <dl>
	 * <!--dt>CV_BLUR_NO_SCALE</dt>
	 * <dd><em>simple blur with no scaling</em></dd>
	 * <dd>for each pixel the result is a sum of pixels values in param1×param2 neighborhood of the 
	 * pixel. If the neighborhood size varies from pixel to pixel, compute the sums using integral 
	 * image (cvIntegral).</dd-->
	 * <dt>CV_BLUR</dt>
	 * <dd><em>simple blur</em></dd>
	 * <dd>for each pixel the result is a mean of pixel values param1×param2 neighborhood of the 
	 * pixel.</dd>
	 * <dt>CV_GAUSSIAN</dt>
	 * <dd><em>Gaussian blur</em></dd>
	 * <dd>the image is smoothed using the Gaussian kernel of size param1×param2. param3 and param4 
	 * may optionally be used to specify shape of the kernel.</dd>
	 * <dt>CV_MEDIAN</dt>
	 * <dd><em>median blur</em></dd>
	 * <dd>the image is smoothed using medial filter of size param1×param1. That is, for each pixel 
	 * the result is the median computed over param1×param1 neighborhood.</dd>
	 * <dt>CV_BILATERAL</dt><dd>bilateral filter</dd>
	 * <dd>the image is smoothed using a bilateral 3x3 filter with color sigma=param1 and space 
	 * sigma=param2. Information about bilateral filtering can be found at 
	 * <a href="http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html">
	 * Bilateral Filtering</a></dd>
	 * </dl>
	 *
	 * @param param1	The first parameter of smoothing operation. It should be odd (1, 3, 5, …), 
	 *					so that a pixel neighborhood used for smoothing operation is symmetrical 
	 *					relative to the pixel.
	 *
	 * @see #blur( int, int, int, float, float )
	 */
	public void blur( int type, int param1 ) {
		blur( type, param1, 0, 0f, 0f );
	}
	
	/**
	 * Smooth the image in one of several ways.
	 *
	 * @param param1	The first parameter of smoothing operation. It should be odd (1, 3, 5, …), 
	 *					so that a pixel neighborhood used for smoothing operation is symmetrical 
	 *					relative to the pixel.
	 * @param param2	The second parameter of smoothing operation. In case of simple 
	 *					scaled/non-scaled and Gaussian blur if param2 is zero, it is set to param1.
	 *					When not 0, it should be odd too.
	 * @param param3	In case of Gaussian kernel this parameter may specify Gaussian sigma 
	 *					(standard deviation). If it is zero, it is calculated from the kernel size:
	 *					sigma = (n/2 - 1)*0.3 + 0.8, where n=param1 for horizontal kernel,
	 *					n=param2 for vertical kernel. With the standard sigma for small kernels 
	 *					(3×3 to 7×7) the performance is better. If param3 is not zero, while param1 
	 *					and param2 are zeros, the kernel size is calculated from the sigma 
	 *					(to provide accurate enough operation).
	 * @param param4	In case of non-square Gaussian kernel the parameter may be used to specify a
	 *					different (from param3) sigma in the vertical direction.
	 *
	 * @see #blur( int, int )
	 */
	public native void blur( int type, int param1, int param2, float param3, float param4 );
	
	/**
	 * Set global interpolation method.
	 * By default the interpolation method is set to <code>INTER_LINEAR</code>.
	 * Used by all methods (ex. <code>copy()</code>, <code>loadImage()</code>, …) that resize the image.
	 *
	 * <dl>
	 * <dt>INTER_NN</dt>
	 * <dd>nearest-neighbor (preserve hard egdes)</dd>
	 * <dt>INTER_LINEAR</dt>
	 * <dd>bilinear interpolation</dd>
	 * <dt>INTER_CUBIC</dt>
	 * <dd>bicubic interpolation (best for smooth gradients)</dd>
	 * <dt>INTER_AREA</dt>
	 * <dd>resampling using pixel area relation</dd>
	 * </dl>
	 *
	 * @param method	INTER_NN, INTER_LINEAR, INTER_CUBIC or INTER_AREA
	 * @example copy
	 */
	public native void interpolation( int method );
	
	
	
	/**
	 * Copy an image into the current OpenCV buffer.
	 * <em>Note: any alpha channel will be ignored</em>.
	 *
	 * @description Copy the image (or a part of it) into the current OpenCV buffer (or a part of it).
	 * Resizing allowed.
	 * <em>Note: any alpha channel will be ignored</em>.	 
	 *
	 * @param image	the image to copy into buffer
	 *
	 * @see #allocate(int,int)
	 * @see #interpolation( int )
	 * @see #copy( String )
	 * @see #copy( PImage, int, int, int, int, int, int, int, int )
	 * @see #copy( String, int, int, int, int, int, int, int, int )
	 * @see #copy( int[], int, int, int, int, int, int, int, int, int )
	 */
	public boolean copy( PImage image ) {
		return copy( image, 0, 0 );
	}
	public boolean copy( PImage image, int x, int y ) {
		return copy( image, x, y, image.width, image.height, 0, 0, image.width, image.height );
	}
	
	/**
	 * Copy the specified image file into the current OpenCV buffer.
	 * <em>Note: any alpha channel will be ignored</em>.
	 *
	 * @param file	the filepath of the image to copy into buffer
	 *
	 * @see #allocate(int,int)
	 * @see #interpolation( int )
	 * @see #copy( PImage )
	 * @see #copy( PImage, int, int, int, int, int, int, int, int )
	 * @see #copy( int[], int, int, int, int, int, int, int, int, int )
	 *
	 * @return true on success
	 */
	public boolean copy( String file ) {
		return copy( file, 0, 0 );
	}
	
	public boolean copy( String file, int x, int y ) {
		return copy( file, x, y, -1, -1, 0, 0, -1, -1 );
	}
	
	/**
	 * Copy the image (or a part of it) into the current OpenCV buffer (or a part of it).
	 * Resizing allowed.
	 * <em>Note: any alpha channel will be ignored</em>.
	 *
	 * @param image	the filepath of the image to copy into buffer
	 *
	 * @see #allocate(int,int)
	 * @see #interpolation( int )
	 * @see #copy( OpenCV )
	 * @see #copy( PImage )
	 * @see #copy( String )
	 * @see #copy( String, int, int, int, int, int, int, int, int )
	 * @see #copy( int[], int, int, int, int, int, int, int, int, int )
	 * @see #copy( int[], int, int, int, int, int, int, int, int, int )
	 */
	public boolean copy( PImage image, int sx, int sy, int swidth, int sheight, int dx, int dy, int dwidth, int dheight ) {
		return copy( image.pixels, image.width, sx, sy, swidth, sheight, dx, dy, dwidth, dheight );
	}
	
	/**
	 * Copy the specified image file (or a part of it) into the current OpenCV buffer (or a part of it).
	 * Resizing allowed.
	 * <em>Note: any alpha channel will be ignored</em>.
	 * <p>Supported image formats:</p>
	 * <ul>
	 * <li>Windows bitmaps: *.bmp,*.dib</li>
	 * <li>JPEG files: *.jpeg,*.jpg,*.jpe</li>
	 * <li>JPEG 2000 files: *.jp2</li>
	 * <li>Portable Network Graphics: *.png</li>
	 * <li>Portable image format: *.pbm,*.pgm,*.ppm</li>
	 * <li>Sun rasters: *.sr,*.ras</li>
	 * <li>TIFF files: *.tiff,*.tif</li>
	 * </ul>
	 * <p>
	 * Mac OS X users should also read image formats supported by QuickTime.<br />
	 * For other formats if Processing can read it, proceed a combination between <code>loadImage()</code> and <code>copy(PImage)</code>.
	 * </p>
	 *
	 * @see #allocate(int,int)
	 * @see #interpolation( int )
	 * @see #copy( OpenCV )
	 * @see #copy( PImage )
	 * @see #copy( String )
	 * @see #copy( PImage, int, int, int, int, int, int, int, int )
	 * @see #copy( int[], int, int, int, int, int, int, int, int, int )
	 * @see #copy( int[], int, int, int, int, int, int, int, int, int )
	 *
	 * @return true on success
	 */
	public native boolean copy( String file, int sx, int sy, int swidth, int sheight, int dx, int dy, int dwidth, int dheight );
	
	
	/**
	 * Copies a region of pixels from an image to the current buffer at the specified position and with the given
	 * dimensions.
	 * Resizing allowed.
	 * <em>Note: any alpha channel will be ignored</em>.
	 *
	 * @param pixels	the image data
	 * @param step		the width of one horizontal line of pixels
	 * @param sx		the source x coordinate
	 * @param sy		the source y coordinate
	 * @param swidth	the source width
	 * @param sheight	the source height
	 * @param dx		the destination x coordinate
	 * @param dy		the destination y coordinate
	 * @param dwidth	the destination width
	 * @param dheight	the destination height
	 *
	 * @see #allocate(int,int)
	 * @see #interpolation( int )
	 *
	 * @see #copy( PImage )
	 */
	public native boolean copy( int[] pixels, int step, int sx, int sy, int swidth, int sheight, int dx, int dy, int dwidth, int dheight );
	
	
	/** TODO: REGLER LE PROBLEME DE LA DESTINATION : COPIE ACTUELLEMENT DANS LE BUFFER UNIQUEMENT (C++)
	 
	 public boolean copy( OpenCV source, int srctype ) {
	 copy( source, srctype, BUFFER );
	 }
	 public native boolean copy( OpenCV source, int srctype, int desttype );*/
	public boolean copy( OpenCV source ) {
		return copy( source, BUFFER, BUFFER );
	}
	public boolean copy( OpenCV source, int srctype ) {
		return copy( source, srctype, BUFFER );
	}
	private native boolean copy( OpenCV source, int srctype, int desttype );
	
	
	/**
	 * Revert to the original image.
	 * By default returns to RGB image, or GRAY (if specified).
	 *
	 * @see #blobs( int, int, int, boolean, int )
	 * @see #blobs( int, int, int, boolean )
	 */
	public void restore() { restore(RGB); } // TODO : reset memory ROI if exists
	
	/**
	 * Restore the current image data from the original image with the given color space.
	 *
	 * @param type	the target color space : RGB or GRAY
	 *
	 * @see #blobs( int, int, int, boolean, int )
	 * @see #blobs( int, int, int, boolean )
	 */
	public native void restore( int type );
	
	
	/**
	 * Retrieve current (or specified) image data.
	 *
	 * @description Retrieve current (or specified) image data.
	 * @param type	the type of the image: SOURCE, BUFFER, MEMORY
	 * @return int[]
	 */
	public native int[] pixels( int type );
	
	/**
	 * Retrieve current image data.
	 *
	 * @return int[]
	 */
	public int[] pixels() { return pixels( BUFFER ); }
	
	
	/**
	 * Load an image from the specified file.
	 * <p>Currently the following file formats are supported:</p>
	 * <ul>
	 * <li>Windows bitmaps - BMP, DIB</li>
	 * <li>JPEG files - JPEG, JPG, JPE</li>
	 * <li>Portable Network Graphics - PNG</li>
	 * <li>Portable image format - PBM, PGM, PPM</li>
	 * <li>Sun rasters - SR, RAS</li>
	 * <li>TIFF files - TIFF, TIF</li>
	 * </ul>
	 * <p><em>note : this method automatically updates previous memory allocation</em></p>
	 *
	 * Currently there is an impressive OpenCV-caused memory leak on Macintosh computers
	 * when recalling this method successively. To fix this bug, load the image file from
	 * Processing and pass the pixels over using <code>copy()</code>.
	 *
	 * @param file	String : the name of file to be loaded
	 *
	 * @see #loadImage( String, int, int )
	 * @return true on sucess
	 */
	public boolean loadImage( String file ) {
		return loadImage( file, -1, -1 );
	}
	
	/**
	 * Load an image from the specified file with the given size dependin of the current scale 
	 * interpolation method.
	 * <p>Currently the following file formats are supported:</p>
	 * <ul>
	 * <li>Windows bitmaps - BMP, DIB</li>
	 * <li>JPEG files - JPEG, JPG, JPE</li>
	 * <li>Portable Network Graphics - PNG</li>
	 * <li>Portable image format - PBM, PGM, PPM</li>
	 * <li>Sun rasters - SR, RAS</li>
	 * <li>TIFF files - TIFF, TIF</li>
	 * </ul>
	 * <p><em>note : this method automatically updates previous memory allocation</em></p>
	 *
	 * @param file		the name of file to be loaded
	 * @param width		the destination image (buffer) width size
	 * @param height	the destination image (buffer) height size
	 *
	 * @see #interpolation( int )
	 * @see #loadImage( String )
	 * @return true on sucess
	 */
	public native boolean loadImage( String file, int width, int height );
	
	
	/**
	 * Return the current OpenCV image.
	 *
	 * @description Return the current (or specified) OpenCV image
	 * @see #image(int)
	 * @return PImage
	 * @example capture
	 */
	public PImage image() {  return image(BUFFER);  }
	
	/** Return the specified OpenCV image
	 *
	 * @param type	the type of the image: SOURCE, BUFFER, MEMORY
	 * @see #image()
	 * @return PImage
	 */
	public PImage image( int type ) {
		
		
		// empty image -> display message & exit
		if ( width==0 && height==0 ) {
			System.err.println( "[opencv] FATAL ERROR: could not define source dimensions.\n--" );
			System.err.println( "OpenCV buffer is not allocated for many reason: image not found," );
			System.err.println( "movie file or capture unavailable, or simply not allocated with" );
			System.err.println( "the allocate() method\n" );
			return null;
		}
		
		
		// create image width pixels
		PImage img = new PImage( width, height );
		img.pixels = pixels(type);
		
		// return image
		return img;
	}
	
	
	
	////////////////////////////////////// BLOB'S DETECTION ////////////////////////////////////////
	
	
	/** 
	 * Blob and contour detection.
	 * 
	 * <p>This function looks for contours within the image, returning a list of <code>Blob</code> objects.</p>
	 * <p>When searching for blobs, you must define the minimum and maximum size in pixels. This can be calculated by any number of means; for example, if you want to limit blobs to no larger than half the Region Of Interest, pass <code>(width * height) / 2</code> for the <code>maxArea</code>. Blobs are then ordered from largest to smallest.</p>
	 *
	 * <p><code>Blob</code> objects contain all the relevant information about each contour (area, length, centroid, isHole, …)</p>
	 *
	 * @description Blob and contour detection.
	 * 
	 * <p>This function looks for contours within the image, returning a list of <code>Blob</code> objects.</p>
	 * <p>When searching for blobs, you must define the minimum and maximum size in pixels. For example, if you want to limit blobs to no larger than half the Region Of Interest, pass <code>(width * height) / 2</code> for the <code>maxArea</code>.</p>
	 *
	 * <p>Blobs are returned in order from largest to smallest.</p>
	 *
	 * <p><a href="#"><code>Blob</code></a> objects contain all the relevant information about each contour (area, length, centroid, isHole, …)</p>
	 *
	 * <p>The optional <code>maxVertices</code> parameter, allows you to increase the overall number of points defining the contour of the blob. Use this parameter if for some reason your blob shapes are incomplete. Augementing this parameter can affect performance.</p>
	 *
	 * <p>Careful! This function will damage the current buffered image while searching for contours. If you want to do any subsequent work with this image, you will need to call the <code>restore()</code> method after this one.</p>
	 * 
	 * @param minArea	the minimum area to search for (total pixels)
	 * @param maxArea	the maximum area to search for (total pixels)
	 * @param maxBlobs	the maximim number of blobs to return
	 * @param findHoles	accept blobs fully inside of other blobs
	 *
	 * @see #blobs( int, int, int, boolean, boolean )
	 * @see Blob
	 * @see #restore()
	 * @see #restore( int )
	 * @see #MAX_VERTICES
	 *
	 * @return Blob[]
	 */
	public CvBlob[] blobs( int minArea, int maxArea ) { 
		return blobs( minArea, maxArea, 1 );
	}
	public CvBlob[] blobs( int minArea, int maxArea, int maxBlobs ) { 
		return blobs( minArea, maxArea, maxBlobs, false );
	}
	public CvBlob[] blobs( int minArea, int maxArea, int maxBlobs, boolean findHoles ) { 
		return blobs( minArea, maxArea, maxBlobs, findHoles, true );
	}
	
	/** Blob and contour detection.
	 * 
	 * <p>This function looks for contours within the image, returning a list of <code>Blob</code> objects.</p>
	 * <p>When searching for blobs, you must define the minimum and maximum size in pixels. This can be calculated by any number of means; for example, if you want to limit blobs to no larger than half the Region Of Interest, pass <code>(width * height) / 2</code> for the <code>maxArea</code>. Blobs are then ordered from largest to smallest.</p>
	 *
	 * <p><code>Blob</code> objects contain all the relevant information about each contour (area, length, centroid, isHole, …)</p>
	 *
	 * <!--p>The optional <code>maxVertices</code> parameter, allows you to increase the overall number of points defining the contour of the blob. Use this parameter if for some reason your blob shapes are incomplete.</p-->
	 * 
	 * @param minArea	the minimum area to search for (total pixels)
	 * @param maxArea	the maximum area to search for (total pixels)
	 * @param maxBlobs	the maximim number of blobs to return
	 * @param findHoles	accept blobs fully inside of other blobs
	 * @param maxVertices	the maximum number of points used to define the contour
	 *
	 * @see #blobs( int, int, int, boolean )
	 * @see Blob
	 * @see #restore()
	 * @see #restore( int )
	 * @see #MAX_VERTICES
	 *
	 * @return Blob[]
	 */
	public native CvBlob[] blobs
	( int minArea, int maxArea, int maxBlobs, boolean findHoles, boolean approx );
	
	
	
	
	/////////////////////////////////// CAPTURE AND MOVIE FILE /////////////////////////////////////
	
	
	/**
	 * Allocate and initialize resources for reading a video stream from the default camera.
	 * <br />
	 * <em>notes : <strong>this method automatically updates previous memory allocation</strong>,
	 * if can not retrieve device rate, 60fps will be used by default
	 *
	 * @description Allocate and initialize resources for reading a video stream from a camera.
	 * @param width		the width of the video stream image
	 * @param height	the height of the video stream image
	 *
	 * @see #capture( int, int, int )
	 * @see #capture( int, int, int, int )
	 * @see #movie( String )
	 *
	 * @return true on success
	 */
	public boolean capture( int width, int height ) {
		return capture( width, height, 0 );
	}
	
	/**
	 * Allocate and initialize resources for reading a video stream from the specified camera.
	 * <br />
	 * <em>notes: <strong>this method automatically updates previous memory allocation</strong>,
	 * if can not retrieve device rate, 60fps will be used by default</em>
	 *
	 * @param width		the width of the video stream image
	 * @param height	the height of the video stream image
	 * @param index		the index of the camera to be used
	 *
	 * @see #capture( int, int )
	 * @see #capture( int, int, int, int )
	 * @see #movie( String )
	 * @see #movie( String, int, int )
	 * @see #movie( String, int, int, int )
	 *
	 * @return true on success
	 */
	public boolean capture( int width, int height, int index ) {
		return capture( width, height, index, -1 );
	}
	
	/**
	 * Allocate and initialize resources for reading a video stream from the specified camera and 
	 * the given framerate.
	 * <br /><em>note: <strong>this method automatically updates previous memory allocation</strong></em>
	 *
	 * @param width		the width of the video stream image
	 * @param height	the height of the video stream image
	 * @param index		the index of the camera to be used
	 * @param fps		the framerate of the camera to be used
	 *
	 * @see #capture( int, int )
	 * @see #capture( int, int, int )
	 * @see #movie( String )
	 * @see #movie( String, int, int )
	 * @see #movie( String, int, int, int )
	 *
	 * @return true on success
	 */
	public native boolean capture( int width, int height, int index, float fps );
	
	/**
	 * Allocate and initialize resources for reading a video file from the specified file name.
	 * <br />
	 * Movie must be located in the sketch's data directory, otherwise you must specified the full 
	 * path to access to the movie file without an error.
	 * <br />
	 * <em>notes: <strong>this method automatically updates previous memory allocation</strong>,
	 * if cannot retrieve movie rate 30fps will be used by default, sound will not be available</em>
	 * <p>Supported codecs and file formats depends on the backend video library :</p>
	 * <ul>
	 * <li>Video for Windows (VfW) for Windows users</li>
	 * <li>FFMPEG on Linux</li>
	 * <li>QuickTime for Mac OS X</li>
	 * </ul>
	 * <p>For more information about video on OpenCV or about reading your video files 
	 * on all platforms, see 
	 * <a href="http://opencvlibrary.sourceforge.net/VideoCodecs">VideoCodecs</a></p>
	 *
	 * @param filename	the filepath of the movie file
	 *
	 * @see #movie( String, int, int )
	 * @see #movie( String, int, int, int )
	 * @see #capture( int, int )
	 * @see #capture( int, int, int )
	 * @see #jump( int )
	 * @see #jump( float )
	 * @see #jump( float, int )
	 *
	 * @return true on success
	 */
	public boolean movie( String filename ) {
		return movie( filename, -1, -1 );
	}
	
	
	/**
	 * Allocate and initialize resources for reading a video file from the specified file name, with
	 * the given frames dimensions.
	 * <br />
	 * Movie must be located in the sketch's data directory, otherwise you must specified the full 
	 * path to access to the movie file without an error.
	 * <br />
	 * <em>notes: <strong>this method automatically updates previous memory allocation</strong>,
	 * if cannot retrieve movie rate 30fps will be used by default, sound will not be available</em>
	 * <p>Supported codecs and file formats depends on the backend video library :</p>
	 * <ul>
	 * <li>Video for Windows (VfW) for Windows users</li>
	 * <li>FFMPEG on Linux</li>
	 * <li>QuickTime for Mac OS X</li>
	 * </ul>
	 * <p>For more information about video on OpenCV or about reading your video files 
	 * on all platforms, see 
	 * <a href="http://opencvlibrary.sourceforge.net/VideoCodecs">VideoCodecs</a></p>
	 *
	 * @param filename	the filepath of the movie file
	 * @param width		the width of the movie image
	 * @param height	the height of the movie image
	 *
	 * @see #movie( String )
	 * @see #movie( string, int, int, int )
	 * @see #jump( int )
	 * @see #jump( float )
	 * @see #jump( float, int )
	 *
	 * @return true on success
	 * @example movie
	 */
	public boolean movie( String filename, int width, int height ) {
		return movie( filename, width, height, -1 );
	}
	
	/**
	 * Allocate and initialize resources for reading a video file from the specified file name, with
	 * the given frames dimensions and frame rate.
	 * <br />
	 * This function will automatically update movie frame, no longer need to call the <code>read()
	 * </code> method, except for playing movie image by image. In this case specify 0 as frame rate.
	 * <br />
	 * Movie must be located in the sketch's data directory, otherwise you must specified the full 
	 * path to access to the movie file without an error.
	 * <br />
	 * <em>notes: <strong>this method automatically updates previous memory allocation</strong>,
	 * sound will not be available</em>
	 * <p>Supported codecs and file formats depends on the backend video library :</p>
	 * <ul>
	 * <li>Video for Windows (VfW) for Windows users</li>
	 * <li>FFMPEG on Linux</li>
	 * <li>QuickTime for Mac OS X</li>
	 * </ul>
	 * <p>For more information about video on OpenCV or about reading your video files 
	 * on all platforms, see 
	 * <a href="http://opencvlibrary.sourceforge.net/VideoCodecs">VideoCodecs</a></p>
	 *
	 * @param filename	the filepath of the movie file
	 * @param width		the width of the movie image
	 * @param height	the height of the movie image
	 * @param fps		the framerate to be used for reading movie or 0 to play movie manually
	 *
	 * @see #movie( String )
	 * @see #movie( String, int, int )
	 * @see #read()
	 * @see #jump( int )
	 * @see #jump( float )
	 * @see #jump( float, int )
	 *
	 * @return true on success
	 * @example movie
	 */
	public native boolean movie( String filename, int width, int height, float fps );
	
	/*
	 * @see CvPlayer
	 * @return CvPlayer
	public CvPlayer movie( String filename, int width, int height ) {
		return new CvPlayer( this, filename, width, height );
	}*/
	
	
	
	/**
	 * Start the movie playback or restart camera input stream, 
	 * same as play() but better named for input stream.
	 */
	public native void start();
	
	
	/**
	 * Play the movie file or restart camera input stream, 
	 * same as start() but better named for movie file.
	 */
	public void play() { start(); }

	/**
	 * Returns true when movie file or camera is running
	 * @return boolean
	 */ 
	public native boolean playing();
	
	
	/**
	 * Pauses the movie playback or camera input stream.
	 */
	public native void pause();
	
	/**
	 * Stop the movie playback and place playhead at the begining or stop camera input stream.
	 */
	public native void stop();
	
	
	
	/**
	 * Grab a new frame from the input camera or a movie file.
	 * @example capture
	 */
	public native void read();
	
	/**
	 * Returns true when there is a new frame in movie file or camera input stream
	 * @return true
	 */ 
	public native boolean available();
	
	
	/**
	 * Return the required property from the current capture.
	 *
	 * @param which	either: MOVIE_WIDTH, MOVIE_HEIGHT, MOVIE_FPS, MOVIE_FRAME_COUNT, 
	 * MOVIE_MILLISECONDS, MOVIE_FRAMES, MOVIE_RATIO
	 * @return float
	 */
	public native float property( int which );
	
	
	/**
	 * Jump to a specified movie frame.
	 *
	 * @param millis	the time in milliseconds of the desired frame
	 * @example movie
	 * @see #movie( String )
	 * @see #movie( String, int, int )
	 * @see #jump( float )
	 * @see #jump( float, int )
	 *
	 * @invisible
	 * @deprecated
	 */
	public void jump( int millis ) {
		jump( (float) millis, MOVIE_MILLISECONDS );
	}
	
	/**
	 * Jump to a specified movie frame.
	 * For a ratio equals to 0.0 jump to the begining of the movie, 0.1 to end.
	 *
	 * @param ratio	the time expressed as a ratio (0.0 - 1.0) of the desired frame
	 * @see #jump( int )
	 * @see #jump( float, int )
	 * @see #movie( String )
	 * @see #movie( String, int, int )
	 *
	 * @invisible
	 * @deprecated
	 */	
	public void jump( float ratio ) {
		jump( Math.max(Math.min(ratio,1),0), MOVIE_RATIO );
	}
	
	/**
	 * Jump to a specified movie frame.
	 *
	 * @param value	the time (according to type) of the desired frame
	 * @param type	use: MOVIE_MILLISECONDS, MOVIE_FRAMES or MOVIE_RATIO
	 *
	 * @see #jump( float )
	 * @see #jump( int )
	 * @see #movie( String )
	 * @see #movie( String, int, int )
	 */	
	public native void jump( float value, int type  );
	
	
	
	
	/**
	 * Set image region of interest to the given rectangle.
	 *
	 * This methods isolates a sub-section of the current image for all subsequent activity.
	 *
	 * To clear the Region of Interest back to the entire image, call <code>ROI(null);</code>
	 *
	 * @param rect	the new region of interest or <code>null</code> to reset
	 */
	public void ROI( Rectangle rect ) {
		if ( rect==null ) ROI( 0, 0, width, height );
		else ROI( rect.x, rect.y, rect.width, rect.height );
	}
	public void clearROI() {
		ROI( 0, 0, width, height );
	}
	
	
	
	/**
	 * Set image region of interest to the given rectangle.
	 *
	 * This methods isolates a sub-section of the current image for all subsequent activity.
	 *
	 * To clear the Region of Interest back to the entire image, call <code>ROI(null);</code>
	 *
	 * @param x			the region x-coordinate
	 * @param y			the region y-coordinate
	 * @param width		the region width
	 * @param height	the region height
	 */
	public void ROI( float x, float y, float width, float height ) {
		ROI( (int)x, (int)y, (int)width, (int)height );
	}
	public native void ROI( int x, int y, int width, int height );
	
	
	/**
	 * Prepend the absolute path for the given file name.
	 * <p>
	 * This method try to return a full path to an item in the sketch/program folder, in the data
	 * folder for Processing user, the system OpenCV's resources folder ('data' or 'resources'), 
	 * in any resources folder for Java user.
	 * The search order is the 'data' folder, the current user directory, any resources folder.
	 * </p>
	 *
	 * @param file	the filename to be search
	 * @return String
	 * @invisible
	 */
	public String absolutePath( String file ) {
		
		
		String[] paths = new String[0];
		String pwd,dat,home;
		
		
		
		// retrieve the current and data folders
		// and user home directory
		pwd = parent!=null ? parent.sketchPath("") : System.getProperty("user.dir")+File.separator;
		dat = parent!=null ? parent.dataPath("") : pwd+"data"+File.separator;
		home = System.getProperty("user.home");
		
		
		
		// list paths (in order) depending on which plateform this program is running
		
		if ( OS.indexOf("windows")!=-1 ) {
			
			String[] PATH = System.getProperty("java.library.path").split(";");
			
			for( int i=0; i<PATH.length; i++ ) {
				if ( PATH[i].indexOf("OpenCV")==-1 ) continue;
				
				paths = new String[]{
					dat,
					pwd,
					PATH[i].replaceFirst("bin","")+"data\\haarcascades\\"
				};
				break;
			}
		}
		
		if ( OS.indexOf("mac")!=-1 )
			paths = new String[]{
				dat,
				dat+"/haarcascades/",
				pwd,
				"/System/Library/Frameworks/OpenCV.framework/Resources/",
				"/Library/Frameworks/OpenCV.framework/Resources/",
				home+"/Library/Frameworks/OpenCV.framework/Resources/"
			};
		
		if ( OS.indexOf("linux")!=-1 )
			paths = new String[]{
				dat,
				pwd,
				"/usr/share/opencv/haarcascades/",
				"/usr/local/share/opencv/haarcascades/"
			};
		
		
		
		// return path if file exits in one of these directories (or is already absolute path)
		if ( new File(file).isAbsolute() ) return file;
		for( int i=0; i<paths.length; i++ ) {
			if ( new File(paths[i]+file).exists() ) return paths[i]+file;
		}
		
		
		
		// return path if any JAR resources match the given file
		try {
			return this.getClass().getClassLoader().getResource(file).getPath();
		}
		catch( NullPointerException e ) {;}
		
		
		// if not found, return the given file
		return file;
	}
	
	
	
	
	////////////////////////////////////// OBJECT DETECTION ////////////////////////////////////////
	
	
	
	
	
	/**
	 * Load into memory the descriptor file for a trained cascade classifier.
	 * Required by the object detection method (see <code>detect()</code>).
	 *
	 * <p>While you may use your own cascade description files, this library links as well to a standard family of detection cascades (<code>CASCADE_FRONTALFACE_DEFAULT</code>, <code>CASCADE_FULLBODY</code>, …). These are installed automatically in the Windows installer and most Linux packages. For those using Macs, we have included these files in our <code>opencv-framework-*.*.dmg</code> installer. If you use a different Mac installer, you will have to import these files on your own.</p>
	 *
	 * <p>It is recommended that you avoid loading the file at each cycle.</p>
	 *
	 * <p>Available detection cascade flags :</p>
	 *
	 * <ul>
	 * <li>CASCADE_FRONTALFACE_ALT_TREE</li>
	 * <li>CASCADE_FRONTALFACE_ALT</li>
	 * <li>CASCADE_FRONTALFACE_ALT2</li>
	 * <li>CASCADE_FRONTALFACE_DEFAULT</li>
	 * <li>CASCADE_PROFILEFACE</li>
	 * <li>CASCADE_FULLBODY</li>
	 * <li>CASCADE_LOWERBODY</li>
	 * <li>CASCADE_UPPERBODY</li>
	 * </ul>
	 *
	 * @param file	The filepath, or standard cascade flag (see above) of the Haar classifier cascade file to be used for object detection
	 * @see #detect()
	 * @see #detect( float, int, int, int, int )
	 *
	 * @return true on success
	 * @example faceDetect
	 */
	public native boolean cascade( String file );
	
	
	/**
	 * Detect object(s) in the current image depending on the current cascade description.
	 * <p>This method finds rectangular regions in the current image that are likely to contain objects the 
	 * cascade has been trained to recognize. It returns found regions as a sequence of rectangles.</p>
	 * <p>The default parameters (scale=1.1, min_neighbors=3, flags=0) are tuned for accurate
	 * (but slow) object detection. For a faster operation on real-time images, the more preferable 
	 * settings are: scale=1.2, min_neighbors=2, flags=HAAR_DO_CANNY_PRUNING, 
	 * min_size=<minimum possible face size> (for example, ~1/4 to 1/16 of the image area in case of
	 * video conferencing).</p>
	 
	 * <p>Mode of operation flags:</p>
	 * <dl>
	 *
	 * <dt>HAAR_SCALE_IMAGE<dt>
	 * <dd>for each scale factor used the function will downscale the image rather than "zoom" the feature coordinates in the classifier cascade. Currently, the option can only be used alone, i.e. the flag can not be set together with the others.</dd>
	 * <dt>HAAR_DO_CANNY_PRUNING</dt>
	 * <dd>If it is set, the function uses Canny edge detector to reject some image regions that contain too few or too much edges and thus can not contain the searched object. The particular threshold values are tuned for face detection and in this case the pruning speeds up the processing.</dd>
	 * <dt>HAAR_FIND_BIGGEST_OBJECT</dt>
	 * <dd>If it is set, the function finds the largest object (if any) in the image. That is, the output sequence will contain one (or zero) element(s).</dd>
	 * <dt>HAAR_DO_ROUGH_SEARCH</dt>
	 * <dd>It should be used only when CV_HAAR_FIND_BIGGEST_OBJECT is set and min_neighbors > 0. If the flag is set, the function does not look for candidates of a smaller size as soon as it has found the object (with enough neighbor candidates) at the current scale. Typically, when min_neighbors is fixed, the mode yields less accurate (a bit larger) object rectangle than the regular single-object mode (flags=HAAR_FIND_BIGGEST_OBJECT), but it is much faster, up to an order of magnitude. A greater value of min_neighbors may be specified to improve the accuracy.</dd>
	 * </dl>
	 * <p>Note, that in single-object mode HAAR_DO_CANNY_PRUNING does not improve performance much and can even slow down the processing.</p>
	 *
	 *
	 * @param scale	The factor by which the search window is scaled between the subsequent scans, for example, 1.1 means increasing window by 10%.
	 * @param min_neighbors	Minimum number (minus 1) of neighbor rectangles that makes up an object. All the groups of a smaller number of rectangles than min_neighbors-1 are rejected. If min_neighbors is 0, the function does not any grouping at all and returns all the detected candidate rectangles, which may be useful if the user wants to apply a customized grouping procedure.
	 * @param flags	Mode of operation. It can be a combination of zero or more of the above flags.
	 * @param min_width	Minimum window size. By default, it is set to the size of samples the classifier has been trained on (~20×20 for face detection).
	 * @param min_height	Minimum window size. By default, it is set to the size of samples the classifier has been trained on (~20×20 for face detection).
	 *
	 *
	 * @see #cascade( String )
	 * @example faceDetect
	 */
	public native Rectangle[] detect( float scale, int min_neighbors, int flags, int min_width, int min_height );
	public Rectangle[] detect() {
		return detect( 1.1f, 3, 0, 0, 0 );
	}
	
	
}
