content: package edu.stanford.rsl.tutorial.modelObserver;
  
  import edu.stanford.rsl.conrad.data.numeric.Grid2D;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
  import edu.stanford.rsl.conrad.numerics.SimpleOperators;
  import edu.stanford.rsl.conrad.numerics.SimpleVector;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix.InversionType;
  
  /**
   * @author Iris Kellermann
   */
  
  public class Observer {
  
  	/**
  	 * Calculates the difference of the mean images of the given image arrays.  
  	 * @param objectImages The array of images with present object.
  	 * @param emptyImages The array of empty images.
  	 * @return  The mean difference image.
  	 */
  	public static SimpleMatrix GetMeanDifferenceImage(SimpleMatrix[] objectImages, SimpleMatrix[] emptyImages)
  	{
  		try
  		{
  			SimpleMatrix meanObjectImage = ImageHelper.GetMeanImage(objectImages);
  		
  			SimpleMatrix meanEmptyImage = ImageHelper.GetMeanImage(emptyImages);
  		
  			meanObjectImage.subtract(meanEmptyImage);
  			
  			return meanObjectImage;
  		}
  		catch(Exception e)
  		{
  			System.out.println(e.getMessage());
  		}
  		
  		return null;
  	}
  
  	/**
  	 * Calculates the mean covariance matrix of channelized image arrays.  
  	 * @param objectImages The array of images with present object.
  	 * @param emptyImages The array of empty images.
  	 * @param channelMatrix The matrix containing the channel image vectors.
  	 * @return  The result matrix.
  	 */
  	public static SimpleMatrix GetCovarianceMatrix(SimpleMatrix[] objectImages, SimpleMatrix[] emptyImages, SimpleMatrix channelMatrix)
  	{
  		SimpleMatrix meanObjectImage = ImageHelper.GetMeanImage(objectImages);
  		SimpleMatrix meanEmptyImage = ImageHelper.GetMeanImage(emptyImages);
  		
  		SimpleMatrix[] MeanCovariance = new SimpleMatrix[2]; 
  		MeanCovariance[0] = new SimpleMatrix	(channelMatrix.getCols(), channelMatrix.getCols());
  		MeanCovariance[1] = new SimpleMatrix	(channelMatrix.getCols(), channelMatrix.getCols());
  				
  		for(int i = 0; i < objectImages.length; ++i)
  		{
  			SimpleVector differenceImage = ImageHelper.ConvertSimpleMatrixToVector(SimpleOperators.subtract(objectImages[i], meanObjectImage));
  			SimpleVector channelizedImage = SimpleOperators.multiply(channelMatrix.transposed(), differenceImage);
  		
  			MeanCovariance[0].add(SimpleOperators.multiplyOuterProd(channelizedImage, channelizedImage));
  		}			
  		
  		MeanCovariance[0].divideBy(objectImages.length);
  		
  		for(int i = 0; i < emptyImages.length; ++i)
  		{
  			SimpleVector differenceImage = ImageHelper.ConvertSimpleMatrixToVector(SimpleOperators.subtract(emptyImages[i], meanEmptyImage));
  			SimpleVector channelizedImage = SimpleOperators.multiply(channelMatrix.transposed(), differenceImage);
  		
  			MeanCovariance[1].add(SimpleOperators.multiplyOuterProd(channelizedImage, channelizedImage));
  		}
  		
  		MeanCovariance[1].divideBy(emptyImages.length);
  				
  		//mean of covariance matrixes
  		return ImageHelper.GetMeanImage(MeanCovariance);
  	}
  
  	/**
  	 * Creates the template for the observer.  
  	 * @param testModels The array of images with present object.
  	 * @param emptyImages The array of empty images.
  	 * @param channelMatrix The matrix containing the channel image vectors.
  	 * @return  The result value.
  	 */
  	public static SimpleVector CreateTemplate(Grid2D[] testModels, Grid2D[] emptyImages, SimpleMatrix channelMatrix)
  	{
  		//convert Grid2D images to SimpleMatrix
  		SimpleMatrix[] objectImagesMatrix = new SimpleMatrix[testModels.length];
  		SimpleMatrix[] emptyImagesMatrix = new SimpleMatrix[emptyImages.length];
  		
  		for(int i = 0; i < testModels.length; ++i)
  		{
  			objectImagesMatrix[i] = ImageHelper.ConvertGrid2DToSimpleMatrix(testModels[i]);
  		}
  		for(int i = 0; i < emptyImages.length; ++i)
  		{
  			emptyImagesMatrix[i] = ImageHelper.ConvertGrid2DToSimpleMatrix(emptyImages[i]);
  		}
  		
  		
  		SimpleMatrix meanDifferenceImage = Observer.GetMeanDifferenceImage(objectImagesMatrix, emptyImagesMatrix);
  					
  		SimpleMatrix covarianceMatrix = Observer.GetCovarianceMatrix(objectImagesMatrix, emptyImagesMatrix, channelMatrix);
  		
  		//convert meanDifferenceImage to columns
  		SimpleVector meanDifferenceVector = ImageHelper.ConvertSimpleMatrixToVector(meanDifferenceImage);
  		
  		//calculate channelized mean-difference image s_v
  		SimpleVector s_v = SimpleOperators.multiply(channelMatrix.transposed(), meanDifferenceVector);
  			
  		//create template
  		SimpleMatrix C_vInverted = covarianceMatrix.inverse(InversionType.INVERT_QR);
  		
  		SimpleVector templateVector = SimpleOperators.multiply(s_v, C_vInverted);
  		
  		return templateVector;
  	}
  	
  	/**
  	 * Calculates the result of the observer.  
  	 * @param model The test model.  
  	 * @param template The template of the observer.
  	 * @param channelMatrix The matrix containing the channel image vectors.
  	 * @return  The result value.
  	 */
  	public static double GetResultValue(Grid2D model, SimpleVector template, SimpleMatrix channelMatrix)
  	{
  		//convert Grid2D images to SimpleMatrix
  		SimpleVector modelVector = ImageHelper.ConvertSimpleMatrixToVector(ImageHelper.ConvertGrid2DToSimpleMatrix(model));
  		
  		//the channelized model image
  		SimpleVector vVector = SimpleOperators.multiply(channelMatrix.transposed(), modelVector);
  		
  		double resultValue = SimpleOperators.multiplyInnerProd(template, vVector);
  				
  		return resultValue;
  	}
  }
  
  /*
   * Copyright (C) 2010-2014 - Iris Kellermann 
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */