// Catalano Imaging Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.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
//
package Catalano.Imaging.Filters;
import Catalano.Imaging.FastBitmap;
import Catalano.Math.Decompositions.SingularValueDecomposition;
import Catalano.Math.Matrix;
import Catalano.Statistics.Tools;
/**
* Principal Component Transform.
* @author Diego Catalano
*/
public class PrincipalComponentTransform {
/**
* Component.
*/
public static enum Component{
/**
* Red channel.
*/
Red,
/**
* Green channel.
*/
Green,
/**
* Blue Channel.
*/
Blue,
/**
* RGB.
*/
RGB
};
private double[][] image;
private int width;
private int height;
/**
* Initialize a new instance of the PrincipalComponentTransform class.
*/
public PrincipalComponentTransform() {}
/**
* Compute PCA in the image.
* @param fastBitmap Image to be processed.
*/
public void Compute(FastBitmap fastBitmap){
if(fastBitmap.isRGB()){
this.width = fastBitmap.getWidth();
this.height = fastBitmap.getHeight();
//Transform the image in vectors
int size = fastBitmap.getSize();
this.image = new double[size][3];
for (int i = 0; i < size; i++) {
image[i][0] = fastBitmap.getRed(i);
image[i][1] = fastBitmap.getGreen(i);
image[i][2] = fastBitmap.getBlue(i);
}
//Run the PCA
double[] means = getMeans(image);
//Center the data
image = Center(image, means);
//Find the eigen vectors.
SingularValueDecomposition svd = new SingularValueDecomposition(image, false, true);
image = Matrix.Multiply(image, svd.getV());
}
else{
throw new IllegalArgumentException("Principal Component Transform only works in RGB images.");
}
}
private double[] getMeans(final double[][] matrix){
double[] means = new double[matrix[0].length];
for (int i = 0; i < matrix[0].length; i++) {
double[] col = Matrix.getColumn(matrix, i);
means[i] = Tools.Mean(col);
}
return means;
}
private double[][] Center(double[][] matrix, double[] means){
double[][] m = new double[matrix.length][matrix[0].length];
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[0].length; j++) {
m[i][j] = matrix[i][j] - means[j];
}
}
return m;
}
/**
* Extract principal component from the image.
* @param component Component.
* @return Principal component of the color.
*/
public FastBitmap Extract(Component component){
if(component == Component.Red){
//Find the min and max values
double min = Matrix.Min(Matrix.getColumn(image, 0));
double max = Matrix.Max(Matrix.getColumn(image, 0));
FastBitmap fb = new FastBitmap(width, height, FastBitmap.ColorSpace.Grayscale);
int size = width * height;
for (int i = 0; i < size; i++) {
int c = (int)Catalano.Math.Tools.Scale(min, max, 0, 255, image[i][0]);
fb.setGray(i, c);
}
return fb;
}
else if(component == Component.Green){
//Find the min and max values
double min = Matrix.Min(Matrix.getColumn(image, 1));
double max = Matrix.Max(Matrix.getColumn(image, 1));
FastBitmap fb = new FastBitmap(width, height, FastBitmap.ColorSpace.Grayscale);
int size = width * height;
for (int i = 0; i < size; i++) {
int c = (int)Catalano.Math.Tools.Scale(min, max, 0, 255, image[i][1]);
fb.setGray(i, c);
}
return fb;
}
else if (component == Component.Blue){
//Find the min and max values
double min = Matrix.Min(Matrix.getColumn(image, 2));
double max = Matrix.Max(Matrix.getColumn(image, 2));
FastBitmap fb = new FastBitmap(width, height, FastBitmap.ColorSpace.Grayscale);
int size = width * height;
for (int i = 0; i < size; i++) {
int c = (int)Catalano.Math.Tools.Scale(min, max, 0, 255, image[i][2]);
fb.setGray(i, c);
}
return fb;
}
else{
//Find the min and max values
double minRed = Matrix.Min(Matrix.getColumn(image, 0));
double maxRed = Matrix.Max(Matrix.getColumn(image, 0));
double minGreen = Matrix.Min(Matrix.getColumn(image, 1));
double maxGreen = Matrix.Max(Matrix.getColumn(image, 1));
double minBlue = Matrix.Min(Matrix.getColumn(image, 2));
double maxBlue = Matrix.Max(Matrix.getColumn(image, 2));
FastBitmap fb = new FastBitmap(width, height, FastBitmap.ColorSpace.RGB);
int size = width * height;
for (int i = 0; i < size; i++) {
int r = (int)Catalano.Math.Tools.Scale(minRed, maxRed, 0, 255, image[i][0]);
int g = (int)Catalano.Math.Tools.Scale(minGreen, maxGreen, 0, 255, image[i][1]);
int b = (int)Catalano.Math.Tools.Scale(minBlue, maxBlue, 0, 255, image[i][2]);
fb.setRGB(i, r,g,b);
}
return fb;
}
}
}
Ads help maintain this website.