Added new filters and remove face detection(it didn't work)

This commit is contained in:
Ziver Koc 2009-08-29 17:42:06 +00:00
parent 41c474d2a5
commit 73be002969
18 changed files with 497 additions and 362 deletions

View file

@ -22,12 +22,19 @@ public abstract class ImageFilterProcessor {
/** /**
* Sets the listener * Sets the listener
* @param listener The listener, null to disable the progress * @param listener is the listener, null to disable the progress
*/ */
public void setProgressListener(ProgressListener listener){ public void setProgressListener(ProgressListener listener){
this.progress = listener; this.progress = listener;
} }
/**
* Returns the listener
*/
public ProgressListener getProgressListener(){
return this.progress;
}
/** /**
* Sets the progress in percent * Sets the progress in percent
*/ */
@ -65,23 +72,23 @@ public abstract class ImageFilterProcessor {
// converts the img to raw data // converts the img to raw data
int[][][] data = convertToArray(img, cols, rows); int[][][] data = convertToArray(img, cols, rows);
//processes the image //processes the image
process(data); data = process(data);
//converts back the image //converts back the image
return convertToImage(data, data[0].length, data.length); return convertToImage(data, data[0].length, data.length);
} }
/** /**
* Creates a Integer array whit the pixel data of the image * Creates a Integer array with the pixel data of the image
* int[row][col][4] * int[row][col][4]
* 0 -> Alpha data * 0 -> Alpha data
* Red data * Red data
* Green data * Green data
* 4 -> Blue data * 4 -> Blue data
* *
* @param img The image to convert * @param img is the image to convert
* @param cols Columns of the image * @param cols is the columns of the image
* @param rows Rows of the image * @param rows is the rows of the image
* @return A Integer array * @return A is the integer array
* @throws InterruptedException * @throws InterruptedException
*/ */
public static int[][][] convertToArray(BufferedImage img, int cols, int rows) throws InterruptedException{ public static int[][][] convertToArray(BufferedImage img, int cols, int rows) throws InterruptedException{
@ -101,13 +108,13 @@ public abstract class ImageFilterProcessor {
// Reading in the color data // Reading in the color data
for(int x=0; x<cols ;x++){ for(int x=0; x<cols ;x++){
//Alpha data //Alpha data
data[y][x][0] = (aRow[x] >> 24) & 0xFF; data[y][x][0] = ((aRow[x] >> 24) & 0xFF);
//Red data //Red data
data[y][x][1] = (aRow[x] >> 16) & 0xFF; data[y][x][1] = ((aRow[x] >> 16) & 0xFF);
//Green data //Green data
data[y][x][2] = (aRow[x] >> 8) & 0xFF; data[y][x][2] = ((aRow[x] >> 8) & 0xFF);
//Blue data //Blue data
data[y][x][3] = (aRow[x])& 0xFF; data[y][x][3] = ((aRow[x])& 0xFF);
} }
} }
return data; return data;
@ -117,9 +124,9 @@ public abstract class ImageFilterProcessor {
/** /**
* Converts a pixel data array to a java Image object * Converts a pixel data array to a java Image object
* *
* @param pixels The pixel data array * @param pixels is the pixel data array
* @param cols Columns of the image * @param cols is the columns of the image
* @param rows Rows of the image * @param rows is the rows of the image
* @return A Image * @return A Image
*/ */
public static BufferedImage convertToImage(int[][][] pixels, int cols, int rows){ public static BufferedImage convertToImage(int[][][] pixels, int cols, int rows){
@ -148,20 +155,22 @@ public abstract class ImageFilterProcessor {
} }
/** /**
* Runs the image thrue the processor * Runs the image thru the processor
* @param data The raw image to apply the effect to * @param data is the raw image to apply the effect to. This will NOT be altered
*/ */
public void process(final int[][][] data){ public int[][][] process(int[][][] data){
process(data, 0, 0, data[0].length, data.length); return process(data, 0, 0, data[0].length, data.length);
} }
/** /**
* The underlying effect is run here * The underlying effect is run here
* @param data The raw image to apply the effect to *
* @param data is the raw image to apply the effect to. This will NOT be altered
* @param startX is the x pixel of the image to start from * @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from * @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop * @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop * @param stopY is the y pixel of the image to stop
* @return either the modified data parameter or an new array
*/ */
public abstract void process(final int[][][] data, int startX, int startY, int stopX, int stopY); public abstract int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY);
} }

View file

@ -17,8 +17,8 @@ public class ImageUtil {
* @param stopY is the y pixel of the image to stop * @param stopY is the y pixel of the image to stop
* @return The peak value of the image * @return The peak value of the image
*/ */
public static int peakValue(int[][][] data) { public static int getPeakValue(int[][][] data) {
return peakValue(data, 0, 0, data[0].length, data.length); return getPeakValue(data, 0, 0, data[0].length, data.length);
} }
/** /**
@ -31,7 +31,7 @@ public class ImageUtil {
* @param stopY is the y pixel of the image to stop * @param stopY is the y pixel of the image to stop
* @return The peak value of the image * @return The peak value of the image
*/ */
public static int peakValue(int[][][] data, int startX, int startY, int stopX, int stopY) { public static int getPeakValue(int[][][] data, int startX, int startY, int stopX, int stopY) {
int peak = 0; int peak = 0;
for(int y=startY; y<stopY ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){ for(int x=startX; x<stopX ;x++){
@ -95,7 +95,7 @@ public class ImageUtil {
* @param stopY is the y pixel of the image to stop * @param stopY is the y pixel of the image to stop
* @return The RMS value for the image * @return The RMS value for the image
*/ */
public static int rms(int[][][] data, int startX, int startY, int stopX, int stopY){ public static int getRMS(int[][][] data, int startX, int startY, int stopX, int stopY){
int pixelCount = 0; int pixelCount = 0;
long accum = 0; long accum = 0;
for(int y=startY; y <stopY ;y++){ for(int y=startY; y <stopY ;y++){
@ -114,12 +114,12 @@ public class ImageUtil {
/** /**
* Multiplies the given image data by the given value * Multiplies the given image data by the given value
* *
* @param data The image data * @param data is the image data
* @param startX is the x pixel of the image to start from * @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from * @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop * @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop * @param stopY is the y pixel of the image to stop
* @param scale The number to scale the image by * @param scale is the number to scale the image color by
*/ */
public static void scale(int[][][] data, int startX, int startY, int stopX, int stopY, double scale){ public static void scale(int[][][] data, int startX, int startY, int stopX, int stopY, double scale){
for(int y=startY; y<stopY ;y++){ for(int y=startY; y<stopY ;y++){
@ -134,54 +134,114 @@ public class ImageUtil {
/** /**
* Returns the mean value of the given image data * Returns the mean value of the given image data
* *
* @param data The image data * @param data is the image data
* @return The mean value of the image * @return the mean value of the image
*/ */
public static int meanValue(int[][][] data){ public static int getMeanValue(int[][][] data){
return meanValue(data, 0, 0, data[0].length, data.length); return getMeanValue(data, 0, 0, data[0].length, data.length);
} }
/** /**
* Returns the mean value of the given image data * Returns the mean value of the given image data
* *
* @param data The image data * @param data is the image data
* @param startX is the x pixel of the image to start from * @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from * @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop * @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop * @param stopY is the y pixel of the image to stop
* @return The mean value of the image * @return the mean value of the image
*/ */
public static int meanValue(int[][][] data, int startX, int startY, int stopX, int stopY){ public static int getMeanValue(int[][][] data, int startX, int startY, int stopX, int stopY){
int pixelCount = 0; int[] tmp = getMeanArray(data, startX, startY, stopX, stopY);
long accum = 0; return (tmp[0] + tmp[1] + tmp[2])/3;
}
/**
* Returns an mean array containing a mean value for each color
*
* @param data is the image data
* @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop
* @return the mean value of the image
*/
public static int[] getMeanArray(int[][][] data, int startX, int startY, int stopX, int stopY){
int mean[] = new int[3];
for(int y=startY; y<stopY ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){ for(int x=startX; x<stopX ;x++){
accum += data[y][x][1]; mean[0] += data[y][x][1];
accum += data[y][x][2]; mean[1] += data[y][x][2];
accum += data[y][x][3]; mean[2] += data[y][x][3];
pixelCount += 3;
} }
} }
// calculate the mean value // calculate the mean value
return (int)(accum/pixelCount); int pixelCount = (stopY-startY)*(stopX-startX);
mean[0] /= pixelCount;
mean[1] /= pixelCount;
mean[2] /= pixelCount;
return mean;
}
/**
* removes the mean value from the image data
*
* @param data is the image data
* @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop
* @param mean is the mean value
*/
public static void remMeanValue(int[][][] data, int startX, int startY, int stopX, int stopY, int mean){
addMeanValue(data, startX, startY, stopX, stopY, -mean);
} }
/** /**
* Adds the mean value to the image data * Adds the mean value to the image data
* *
* @param data The image data * @param data is the image data
* @param startX is the x pixel of the image to start from * @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from * @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop * @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop * @param stopY is the y pixel of the image to stop
* @param mean The mean value * @param mean is the mean value
*/ */
public static void addMeanValue(int[][][] data, int startX, int startY, int stopX, int stopY, int mean){ public static void addMeanValue(int[][][] data, int startX, int startY, int stopX, int stopY, int mean){
addMeanArray(data, startX, startY, stopX, stopY, new int[]{mean, mean, mean});
}
/**
* removes an mean array containing a mean value for each color
*
* @param data is the image data
* @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop
* @param mean is an array of length 3 containing a mean value for each color RGB
*/
public static void remMeanArray(int[][][] data, int startX, int startY, int stopX, int stopY, int[] mean){
addMeanArray(data, startX, startY, stopX, stopY, new int[]{-mean[0], -mean[1], -mean[2]});
}
/**
* Adds an mean array containing a mean value for each color
*
* @param data is the image data
* @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop
* @param mean is an array of length 3 containing a mean value for each color RGB
*/
public static void addMeanArray(int[][][] data, int startX, int startY, int stopX, int stopY, int[] mean){
for(int y=startY; y<stopY ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){ for(int x=startX; x<stopX ;x++){
data[y][x][1] += mean; data[y][x][1] += mean[0];
data[y][x][2] += mean; data[y][x][2] += mean[1];
data[y][x][3] += mean; data[y][x][3] += mean[2];
} }
} }
} }
@ -309,5 +369,4 @@ public class ImageUtil {
else else
return color; return color;
} }
} }

View file

@ -28,10 +28,11 @@ public class BlurFilter extends ImageFilterProcessor{
} }
@Override @Override
public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) { public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int inputPeak = ImageUtil.peakValue(data); int inputPeak = ImageUtil.getPeakValue(data);
int[][][] tmpData = new int[data.length][data[0].length][4]; int[][][] tmpData = new int[data.length][data[0].length][4];
int[][][] output = ImageUtil.copyArray(data);
//Perform the convolution one or more times in succession //Perform the convolution one or more times in succession
int redSum, greenSum, blueSum, outputPeak; int redSum, greenSum, blueSum, outputPeak;
for(int i=0; i<blurValue ;i++){ for(int i=0; i<blurValue ;i++){
@ -39,44 +40,44 @@ public class BlurFilter extends ImageFilterProcessor{
for(int y=startY; y<stopY ;y++){ for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, (blurValue-1)*(stopY-startY-2), i*(stopY-startY-2)+y)); setProgress(ZMath.percent(0, (blurValue-1)*(stopY-startY-2), i*(stopY-startY-2)+y));
for(int x=startX; x<stopX ;x++){ for(int x=startX; x<stopX ;x++){
if(x == 0 || x == data[0].length-1 || y == 0 || y == data.length-1){ if(x == 0 || x == output[0].length-1 || y == 0 || y == output.length-1){
redSum = data[y][x][1] * 9; redSum = output[y][x][1] * 9;
greenSum = data[y][x][2] * 9; greenSum = output[y][x][2] * 9;
blueSum = data[y][x][3] * 9; blueSum = output[y][x][3] * 9;
} }
else{ else{
redSum = redSum =
data[y - 1][x - 1][1] + output[y - 1][x - 1][1] +
data[y - 1][x - 0][1] + output[y - 1][x - 0][1] +
data[y - 1][x + 1][1] + output[y - 1][x + 1][1] +
data[y - 0][x - 1][1] + output[y - 0][x - 1][1] +
data[y - 0][x - 0][1] + output[y - 0][x - 0][1] +
data[y - 0][x + 1][1] + output[y - 0][x + 1][1] +
data[y + 1][x - 1][1] + output[y + 1][x - 1][1] +
data[y + 1][x - 0][1] + output[y + 1][x - 0][1] +
data[y + 1][x + 1][1]; output[y + 1][x + 1][1];
greenSum = greenSum =
data[y - 1][x - 1][2] + output[y - 1][x - 1][2] +
data[y - 1][x - 0][2] + output[y - 1][x - 0][2] +
data[y - 1][x + 1][2] + output[y - 1][x + 1][2] +
data[y - 0][x - 1][2] + output[y - 0][x - 1][2] +
data[y - 0][x - 0][2] + output[y - 0][x - 0][2] +
data[y - 0][x + 1][2] + output[y - 0][x + 1][2] +
data[y + 1][x - 1][2] + output[y + 1][x - 1][2] +
data[y + 1][x - 0][2] + output[y + 1][x - 0][2] +
data[y + 1][x + 1][2]; output[y + 1][x + 1][2];
blueSum = blueSum =
data[y - 1][x - 1][3] + output[y - 1][x - 1][3] +
data[y - 1][x - 0][3] + output[y - 1][x - 0][3] +
data[y - 1][x + 1][3] + output[y - 1][x + 1][3] +
data[y - 0][x - 1][3] + output[y - 0][x - 1][3] +
data[y - 0][x - 0][3] + output[y - 0][x - 0][3] +
data[y - 0][x + 1][3] + output[y - 0][x + 1][3] +
data[y + 1][x - 1][3] + output[y + 1][x - 1][3] +
data[y + 1][x - 0][3] + output[y + 1][x - 0][3] +
data[y + 1][x + 1][3]; output[y + 1][x + 1][3];
} }
tmpData[y][x][0] = data[y][x][0]; tmpData[y][x][0] = output[y][x][0];
tmpData[y][x][1] = redSum; tmpData[y][x][1] = redSum;
tmpData[y][x][2] = greenSum; tmpData[y][x][2] = greenSum;
tmpData[y][x][3] = blueSum; tmpData[y][x][3] = blueSum;
@ -84,8 +85,9 @@ public class BlurFilter extends ImageFilterProcessor{
} }
// getting the new peak value and normalizing the image // getting the new peak value and normalizing the image
outputPeak = ImageUtil.peakValue(tmpData); outputPeak = ImageUtil.getPeakValue(tmpData);
ImageUtil.normalize(data, tmpData, startX, startY, stopX, stopY, ((double)inputPeak)/outputPeak ); ImageUtil.normalize(output, tmpData, startX, startY, stopX, stopY, ((double)inputPeak)/outputPeak );
} }
return output;
} }
} }

View file

@ -7,12 +7,12 @@ import zutil.math.ZMath;
public class ColorIntensityFilter extends ImageFilterProcessor{ public class ColorIntensityFilter extends ImageFilterProcessor{
private boolean invert; private boolean invert;
private int redScale; private double redScale;
private int greenScale; private double greenScale;
private int blueScale; private double blueScale;
public ColorIntensityFilter(BufferedImage img){ public ColorIntensityFilter(BufferedImage img){
this(img, 50, 50, 50, false); this(img, 0.2, 0.2, 0.2, false);
} }
/** /**
@ -21,29 +21,29 @@ public class ColorIntensityFilter extends ImageFilterProcessor{
* @param inv If the image color should be inverted * @param inv If the image color should be inverted
*/ */
public ColorIntensityFilter(BufferedImage img, boolean inv){ public ColorIntensityFilter(BufferedImage img, boolean inv){
this(img, 100, 100, 100, inv); this(img, 0.5, 0.5, 0.5, inv);
} }
/** /**
* Creates a ColorIntensityEffect object with the given values * Creates a ColorIntensityEffect object with the given values
* @param img The image data * @param img The image data
* @param red The scale of red (0-100) * @param red The scale of red (0-1)
* @param green The scale of green (0-100) * @param green The scale of green (0-1)
* @param blue The scale of blue (0-100) * @param blue The scale of blue (0-1)
*/ */
public ColorIntensityFilter(BufferedImage img, int red, int green, int blue){ public ColorIntensityFilter(BufferedImage img, double red, double green, double blue){
this(img, red, green, blue, false); this(img, red, green, blue, false);
} }
/** /**
* Creates a ColorIntensityEffect object with the given values * Creates a ColorIntensityEffect object with the given values
* @param img The image data * @param img The image data
* @param red The scale of red (0-100) * @param red The scale of red (0-1)
* @param green The scale of green (0-100) * @param green The scale of green (0-1)
* @param blue The scale of blue (0-100) * @param blue The scale of blue (0-1)
* @param inv If the image color should be inverted * @param inv If the image color should be inverted
*/ */
public ColorIntensityFilter(BufferedImage img, int red, int green, int blue, boolean inv){ public ColorIntensityFilter(BufferedImage img, double red, double green, double blue, boolean inv){
super(img); super(img);
invert = false; invert = false;
redScale = red; redScale = red;
@ -52,15 +52,16 @@ public class ColorIntensityFilter extends ImageFilterProcessor{
} }
@Override @Override
public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) { public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int[][][] output = new int[data.length][data[0].length][4];
// making sure the scales are right // making sure the scales are right
if(redScale > 100) redScale = 100; if(redScale > 1) redScale = 1;
else if(redScale < 0) redScale = 0; else if(redScale < 0) redScale = 0;
if(greenScale > 100) greenScale = 100; if(greenScale > 1) greenScale = 1;
else if(greenScale < 0) greenScale = 0; else if(greenScale < 0) greenScale = 0;
if(blueScale > 100) blueScale = 100; if(blueScale > 1) blueScale = 1;
else if(blueScale < 0) blueScale = 0; else if(blueScale < 0) blueScale = 0;
// Applying the color intensity to the image // Applying the color intensity to the image
@ -69,19 +70,20 @@ public class ColorIntensityFilter extends ImageFilterProcessor{
for(int x=startX; x<stopX ;x++){ for(int x=startX; x<stopX ;x++){
if(!invert){ if(!invert){
// inversion // inversion
data[y][x][0] = data[y][x][0]; output[y][x][0] = data[y][x][0];
data[y][x][1] = 255 - data[y][x][1] * redScale/100; output[y][x][1] = (int)( 255 - data[y][x][1] * redScale );
data[y][x][2] = 255 - data[y][x][2] * greenScale/100; output[y][x][2] = (int)( 255 - data[y][x][2] * greenScale );
data[y][x][3] = 255 - data[y][x][3] * blueScale/100; output[y][x][3] = (int)( 255 - data[y][x][3] * blueScale );
} }
else{ else{
data[y][x][0] = data[y][x][0]; output[y][x][0] = data[y][x][0];
data[y][x][1] = data[y][x][1] * redScale/100; output[y][x][1] = (int)( data[y][x][1] * redScale );
data[y][x][2] = data[y][x][2] * greenScale/100; output[y][x][2] = (int)( data[y][x][2] * greenScale );
data[y][x][3] = data[y][x][3] * blueScale/100; output[y][x][3] = (int)( data[y][x][3] * blueScale );
} }
} }
} }
return output;
} }
} }

View file

@ -30,14 +30,18 @@ public class ContrastBrightnessFilter extends ImageFilterProcessor{
} }
@Override @Override
public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) { public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int mean = ImageUtil.meanValue(data); int mean = ImageUtil.getMeanValue(data);
ImageUtil.addMeanValue(data, startX, startY, stopX, stopY, mean*(-1)); int[][][] output = ImageUtil.copyArray(data);
ImageUtil.scale(data, startX, startY, stopX, stopY, contrast);
ImageUtil.addMeanValue(data, startX, startY, stopX, stopY, (int)(brightness*mean));
ImageUtil.clip(data , startX, startY, stopX, stopY); ImageUtil.addMeanValue(output, startX, startY, stopX, stopY, mean*(-1));
ImageUtil.scale(output, startX, startY, stopX, stopY, contrast);
ImageUtil.addMeanValue(output, startX, startY, stopX, stopY, (int)(brightness*mean));
ImageUtil.clip(output, startX, startY, stopX, stopY);
return output;
} }
} }

View file

@ -0,0 +1,83 @@
package zutil.image.filters;
import java.awt.image.BufferedImage;
import zutil.image.ImageFilterProcessor;
import zutil.image.ImageUtil;
import zutil.math.ZMath;
/**
* Applies an Convolution kernel to the specified image
*
* @author Ziver
*/
public class ConvolutionFilter extends ImageFilterProcessor{
private double[][] kernel;
protected ConvolutionFilter(BufferedImage img) {
super(img);
}
public ConvolutionFilter(double[][] kernel) {
this(null, kernel);
}
/**
* Applies an Convolution kernel to the specified image
*
* @param img is the image
* @param kernel is the kernel to apply to the image
*/
public ConvolutionFilter(BufferedImage img, double[][] kernel) {
super(img);
this.kernel = kernel;
}
@Override
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
if(kernel == null) this.kernel = generateKernel();
int[][][] tmpData = new int[data.length][data[0].length][4];
int xk_length = kernel[0].length;
int yk_length = kernel.length;
for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, (stopY-startY), y+1));
for(int x=startX; x<stopX ;x++){
tmpData[y][x][0] = data[y][x][0]; // alpha
for(int yk=0; yk<yk_length ;yk++){
for(int xk=0; xk<xk_length ;xk++){
if(0 <= y-yk_length/2+yk && y-yk_length/2+yk < data.length &&
0 <= x-xk_length/2+xk && x-xk_length/2+xk < data[0].length){ // check that its not out of index
tmpData[y][x][1] += data[y-yk_length/2+yk][x-xk_length/2+xk][1] * kernel[yk][xk];
tmpData[y][x][2] += data[y-yk_length/2+yk][x-xk_length/2+xk][2] * kernel[yk][xk];
tmpData[y][x][3] += data[y-yk_length/2+yk][x-xk_length/2+xk][3] * kernel[yk][xk];
}
}
}
}
}
ImageUtil.clip(tmpData, startX, startY, stopX, stopY);
return tmpData;
}
/**
* Returns the kernel or null if it has not been generated yet.
*/
public double[][] getKernel(){
return kernel;
}
/**
* Should be overridden by a subclass
*
* @return an special generated kernel
*/
protected double[][] generateKernel(){
return null;
}
}

View file

@ -38,32 +38,35 @@ public class DitheringFilter extends ImageFilterProcessor{
} }
@Override @Override
public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) { public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int error, index; int error, index;
int[] currentPixel; int[] currentPixel;
int[][][] output = ImageUtil.copyArray(data);
for(int y=startY; y<stopY ;y++){ for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, stopY-startY-1, y)); setProgress(ZMath.percent(0, stopY-startY-1, y));
for(int x=startX; x<stopX ;x++){ for(int x=startX; x<stopX ;x++){
currentPixel = data[y][x]; currentPixel = output[y][x];
index = findNearestColor(currentPixel, palette); index = findNearestColor(currentPixel, palette);
data[y][x] = palette[index]; output[y][x] = palette[index];
for (int i = 1; i < 4; i++) { for (int i = 1; i < 4; i++) {
error = currentPixel[i] - palette[index][i]; error = currentPixel[i] - palette[index][i];
if (x + 1 < data[0].length) { if (x + 1 < output[0].length) {
data[y+0][x+1][i] = ImageUtil.clip( data[y+0][x+1][i] + (error*7)/16 ); output[y+0][x+1][i] = ImageUtil.clip( output[y+0][x+1][i] + (error*7)/16 );
} }
if (y + 1 < data.length) { if (y + 1 < data.length) {
if (x - 1 > 0) if (x - 1 > 0)
data[y+1][x-1][i] = ImageUtil.clip( data[y+1][x-1][i] + (error*3)/16 ); output[y+1][x-1][i] = ImageUtil.clip( output[y+1][x-1][i] + (error*3)/16 );
data[y+1][x+0][i] = ImageUtil.clip( data[y+1][x+0][i] + (error*5)/16 ); output[y+1][x+0][i] = ImageUtil.clip( output[y+1][x+0][i] + (error*5)/16 );
if (x + 1 < data[0].length) if (x + 1 < data[0].length)
data[y+1][x+1][i] = ImageUtil.clip( data[y+1][x+1][i] + (error*1)/16 ); output[y+1][x+1][i] = ImageUtil.clip( output[y+1][x+1][i] + (error*1)/16 );
} }
} }
} }
} }
return output;
} }
private static int findNearestColor(int[] color, int[][] palette) { private static int findNearestColor(int[] color, int[][] palette) {

View file

@ -1,180 +0,0 @@
package zutil.image.filters;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import zutil.image.ImageFilterProcessor;
import zutil.image.ImageUtil;
import zutil.math.ZMath;
public class FaceDetectionFilter extends ImageFilterProcessor{
public FaceDetectionFilter(BufferedImage img) {
super(img);
}
@Override
public void process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int[][][] IRgBy = convertARGBToIRgBy(data, startX, startY, stopX, stopY);
MedianFilter median = new MedianFilter(null, 4*getSCALE(stopX-startX, stopY-startY), new boolean[]{false,false,true,true});
median.process(IRgBy);
setProgress(ZMath.percent(0, 4, 1));
//********* Texture Map ********
median = new MedianFilter(null, 8*getSCALE(stopX-startX, stopY-startY), new boolean[]{false,true,false,false});
int[][][] textureMap = ImageUtil.copyArray(IRgBy);
median.process(IRgBy);
for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){
textureMap[y][x][1] = Math.abs(IRgBy[y][x][1]-textureMap[y][x][1]);
}
}
median = new MedianFilter(null, 12*getSCALE(stopX-startX, stopY-startY), new boolean[]{false,true,false,false});
textureMap = ImageUtil.copyArray(IRgBy);
median.process(textureMap);
setProgress(ZMath.percent(0, 4, 2));
//*********** Hue & Saturation *********
int[][] skinMap = new int[data.length][data[0].length];
int[][] hueMap = new int[data.length][data[0].length];
int[][] saturationMap = new int[data.length][data[0].length];
int hue, saturation;
for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){
// hue = (atan^2(Rg,By))
hue = (int)( Math.atan2(IRgBy[y][x][2], IRgBy[y][x][3]) * 360/2*Math.PI);
// saturation = sqrt(Rg^2+By^2)
saturation = (int) Math.sqrt(IRgBy[y][x][2]*IRgBy[y][x][2] + IRgBy[y][x][3]*IRgBy[y][x][3]);
hueMap[y][x] = hue;
saturationMap[y][x] = saturation;
// (1) texture<4.5, 120<160, 10<60
// (2) texture<4.5, 150<180, 20<80
if((textureMap[y][x][1] < 4.5 && (hue >= 120 && hue <= 160) && (saturation >= 10 && saturation <= 60)) ||
(textureMap[y][x][1] < 4.5 && (hue >= 150 && hue <= 180) && (saturation >= 20 && saturation <= 80)) ){
skinMap[y][x] = 1;
}
}
}
setProgress(ZMath.percent(0, 4, 3));
//************** SkinMap dilation ********************
skinMap = dilation(skinMap , startX, startY, stopX, stopY);
//*****************************************************
setProgress(100);
//return convertArrayToARGBchannel(hueMap, startX, startY, stopX, stopY, -150, 150, 1);
//return convertArrayToARGBchannel(saturationMap, startX, startY, stopX, stopY, 0, 70, 1);
ImageUtil.copyArray(
convertArrayToARGBchannel(skinMap, startX, startY, stopX, stopY, 0, 1, 2),
data, startX, startY, stopX, stopY);
}
private int[][] dilation(int[][] data, int startX, int startY, int stopX, int stopY){
int[][] output = new int[data.length][data[0].length];
int radX = 8;
int radY = 8;
for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){
if(data[y][x] == 1){
for(int dy=y-radY; dy<y+radY ;dy++){
for(int dx=x-radX; dx<x+radX ;dx++){
if(dy >= 0 && dy < data.length && dx >= 0 && dx < data[0].length)
output[dy][dx] = 1;
}
}
}
}
}
return output;
}
/**
* Converts the given data array to a color image
*
* @param data The 2d data
* @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop
* @param min The minimum value in the data
* @param max The maximum value in the data
* @param channel The color channel to apply the data to
* @return A ARGB array
*/
public int[][][] convertArrayToARGBchannel(int[][] data, int startX, int startY, int stopX, int stopY,int min, int max, int channel){
int[][][] output = new int[data.length][data[0].length][4];
for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){
output[y][x][0] = 255;
output[y][x][channel] = (int) ZMath.percent(min, max, data[y][x]);
}
}
return output;
}
/**
* Converts RGB color to log-opponent (IRgBy) with the formula:
* I= [L(R)+L(B)+L(G)]/3
* Rg = L(R)-L(G)
* By = L(B)-[L(G)+L(R)]/2
*
* @param data The RGB data
* @param startX is the x pixel of the image to start from
* @param startY is the y pixel of the image to start from
* @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop
* @return IRgBy data
*/
public int[][][] convertARGBToIRgBy(int[][][] data, int startX, int startY, int stopX, int stopY){
int[][][] output = new int[data.length][data[0].length][4];
for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){
output[y][x][0] = data[y][x][0];
// I= [L(R)+L(B)+L(G)]/3
output[y][x][1] = (
IRgByFunction(data[y][x][1]) +
IRgByFunction(data[y][x][2]) +
IRgByFunction(data[y][x][3])
) / 3;
// Rg = L(R)-L(G)
output[y][x][2] = IRgByFunction(output[y][x][1]) - IRgByFunction(data[y][x][2]);
// By = L(B)-[L(G)+L(R)]/2
output[y][x][3] = IRgByFunction(output[y][x][3]) -
(IRgByFunction(output[y][x][2]) - IRgByFunction(output[y][x][1])) / 2;
}
}
return output;
}
// Helper function to convertToIRgBy()
private int IRgByFunction(int value){
return (int)(105*Math.log10(value+1));
}
private int getSCALE(int width, int height){
return (width+height)/320;
}
public Rectangle getFaceRectangle(){
return null;
}
}

View file

@ -0,0 +1,47 @@
package zutil.image.filters;
import java.awt.image.BufferedImage;
/**
* Blurs an image whit the Gaussian blur algorithm
*
* @author Ziver
*/
public class GaussianBlurFilter extends ConvolutionFilter{
private int size;
private double sigma;
public GaussianBlurFilter(BufferedImage img) {
this(img, 5, 1.4);
}
public GaussianBlurFilter(BufferedImage img, int size, double sigma) {
super(img);
this.size = size;
this.sigma = sigma;
}
protected double[][] generateKernel(){
return gaussianFunction(size, size, sigma);
}
/**
* Generates the kernel from the specified values
*/
public static double[][] gaussianFunction(int size_x, int size_y, double sigma){
double[][] kernel;
int center_x = size_x/2;
int center_y = size_y/2;
kernel = new double[size_y][size_x];
for(int y=0; y<size_y ;y++){
for(int x=0; x<size_x ;x++){
double tmp_x = (double)( (x-center_x)*(x-center_x) )/(2*sigma*sigma);
double tmp_y = (double)( (y-center_y)*(y-center_y) )/(2*sigma*sigma);
kernel[y][x] = 1.0/(2*Math.PI*sigma*sigma) * Math.exp( -(tmp_x + tmp_y) );
}
}
return kernel;
}
}

View file

@ -0,0 +1,45 @@
package zutil.image.filters;
import java.awt.image.BufferedImage;
/**
* The MedianFilter is used for noise reduction and things
*
* @author Ziver
*/
public class MeanBlurFilter extends ConvolutionFilter{
private int windowSize;
/**
* Setup a default MedianFilter
*
* @param img is the image to process
*/
public MeanBlurFilter(BufferedImage img) {
this(img, 10);
}
/**
* Setup a default MedianFilter
*
* @param img is the image to process
* @param pixels is the size of the window
*/
public MeanBlurFilter(BufferedImage img, int pixels) {
super(img);
this.windowSize = pixels;
}
protected double[][] generateKernel(){
double[][] kernel = new double[windowSize][windowSize];
double mean = 1.0/(windowSize*windowSize);
for(int y=0; y<windowSize ;y++){
for(int x=0; x<windowSize ;x++){
kernel[y][x] = mean;
}
}
return kernel;
}
}

View file

@ -61,7 +61,7 @@ public class MedianFilter extends ImageFilterProcessor{
pixelValue[x][y] := colorArray[window width / 2][window height / 2]; pixelValue[x][y] := colorArray[window width / 2][window height / 2];
*/ */
@Override @Override
public void process(int[][][] data, int startX, int startY, int stopX, int stopY) { public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int[][][] tmpData = ImageUtil.copyArray(data); int[][][] tmpData = ImageUtil.copyArray(data);
int edgeX = windowSize / 2; int edgeX = windowSize / 2;
@ -87,16 +87,14 @@ public class MedianFilter extends ImageFilterProcessor{
} }
} }
if(channels[0]) data[y][x][0] = findMedian(tmpArray[0], pixelCount/2); if(channels[0]) tmpData[y][x][0] = findMedian(tmpArray[0], pixelCount/2);
else data[y][x][0] = tmpData[y][x][0]; if(channels[1]) tmpData[y][x][1] = findMedian(tmpArray[1], pixelCount/2);
if(channels[1]) data[y][x][1] = findMedian(tmpArray[1], pixelCount/2); if(channels[2]) tmpData[y][x][2] = findMedian(tmpArray[2], pixelCount/2);
else data[y][x][1] = tmpData[y][x][1]; if(channels[3]) tmpData[y][x][3] = findMedian(tmpArray[3], pixelCount/2);
if(channels[2]) data[y][x][2] = findMedian(tmpArray[2], pixelCount/2);
else data[y][x][2] = tmpData[y][x][2];
if(channels[3]) data[y][x][3] = findMedian(tmpArray[3], pixelCount/2);
else data[y][x][3] = tmpData[y][x][3];
} }
} }
return tmpData;
} }
private int getMedianIndex(int i){ private int getMedianIndex(int i){

View file

@ -3,7 +3,6 @@ package zutil.image.filters;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import zutil.image.ImageFilterProcessor; import zutil.image.ImageFilterProcessor;
import zutil.image.ImageUtil;
import zutil.math.ZMath; import zutil.math.ZMath;
public class ResizeImage extends ImageFilterProcessor{ public class ResizeImage extends ImageFilterProcessor{
@ -37,7 +36,7 @@ public class ResizeImage extends ImageFilterProcessor{
} }
@Override @Override
public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) { public int[][][] process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
if(width < 1){ if(width < 1){
height = (int)(((double)width/(stopX-startX))*(stopY-startY)); height = (int)(((double)width/(stopX-startX))*(stopY-startY));
} }
@ -59,14 +58,6 @@ public class ResizeImage extends ImageFilterProcessor{
} }
} }
ImageUtil.copyArray(newData, data, 0, 0, width, height);
}
/**
* Returns the resulting image after processing
* @return an image or null if not processed
*/
public int[][][] getResult(){
return newData; return newData;
} }
} }

View file

@ -0,0 +1,64 @@
package zutil.image.filters;
import java.awt.image.BufferedImage;
import zutil.image.ImageFilterProcessor;
import zutil.math.ZMath;
/**
* Generates an image that contains the edges of the source image
*
* @author Ziver
* INFO: http://en.wikipedia.org/wiki/Sobel_operator
*/
public class SobelEdgeDetectionFilter extends ImageFilterProcessor{
private static final double[][] xG_kernel = new double[][]{
{+1, 0, -1},
{+2, 0, -2},
{+1, 0, -1}
};
private static final double[][] yG_kernel = new double[][]{
{+1, +2, +1},
{ 0, 0, 0},
{-1, -2, -1}
};
public SobelEdgeDetectionFilter(BufferedImage img) {
super(img);
}
@Override
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
ConvolutionFilter conv = new ConvolutionFilter(xG_kernel);
int[][][] xG = conv.process(data, startX, startY, stopX, stopY);
setProgress(33);
conv = new ConvolutionFilter(yG_kernel);
int[][][] yG = conv.process(data, startX, startY, stopX, stopY);
setProgress(66);
int[][][] output = new int[data.length][data[0].length][4];
for(int y=startY; y<stopY ;y++){
setProgress(66+ZMath.percent(0, (stopY-startY), y+1)/100*34);
for(int x=startX; x<stopX ;x++){
output[y][x][0] = data[y][x][0];
output[y][x][1] = (int)Math.sqrt( xG[y][x][1]*xG[y][x][1] + yG[y][x][1]*yG[y][x][1] );
output[y][x][2] = (int)Math.sqrt( xG[y][x][2]*xG[y][x][2] + yG[y][x][2]*yG[y][x][2] );
output[y][x][3] = (int)Math.sqrt( xG[y][x][3]*xG[y][x][3] + yG[y][x][3]*yG[y][x][3] );
/*
output[y][x][1] = Math.abs( xG[y][x][1] ) + Math.abs(yG[y][x][1] );
output[y][x][2] = Math.abs( xG[y][x][2] ) + Math.abs(yG[y][x][2] );
output[y][x][3] = Math.abs( xG[y][x][3] ) + Math.abs(yG[y][x][3] );
*/
}
}
// gradient's direction:
// 0 = arctan( yG/xG )
return output;
}
}

View file

@ -41,10 +41,12 @@ public class SpotLightFilter extends ImageFilterProcessor{
} }
@Override @Override
public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) { public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
if(xPos < 0) xPos = data[0].length/2; if(xPos < 0) xPos = data[0].length/2;
if(yPos < 0) yPos = data.length/2; if(yPos < 0) yPos = data.length/2;
int[][][] output = new int[data.length][data[0].length][4];
double scale, dx, dy, distance; double scale, dx, dy, distance;
for(int y=startY; y<stopY ;y++){ for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, (stopY-startY)-1, y)); setProgress(ZMath.percent(0, (stopY-startY)-1, y));
@ -61,12 +63,13 @@ public class SpotLightFilter extends ImageFilterProcessor{
scale = 1-(distance/radius); scale = 1-(distance/radius);
} }
data[y][x][0] = data[y][x][0]; output[y][x][0] = data[y][x][0];
data[y][x][1] = ImageUtil.clip((int)(scale * data[y][x][1])); output[y][x][1] = ImageUtil.clip((int)(scale * data[y][x][1]));
data[y][x][2] = ImageUtil.clip((int)(scale * data[y][x][2])); output[y][x][2] = ImageUtil.clip((int)(scale * data[y][x][2]));
data[y][x][3] = ImageUtil.clip((int)(scale * data[y][x][3])); output[y][x][3] = ImageUtil.clip((int)(scale * data[y][x][3]));
} }
} }
return output;
} }
} }

View file

@ -76,9 +76,9 @@ public class BloomFilter<T extends Serializable> implements Set<T>, Serializable
} }
/** /**
* @param o The Serializable object to search for * @param o is the Serializable object to search for
* @return If the object contains in the filter or false * @return If the object contains in the filter or
* if the Object is not Serializable * false if the Object is not Serializable
*/ */
public boolean contains(Object o) { public boolean contains(Object o) {
try { try {
@ -131,7 +131,7 @@ public class BloomFilter<T extends Serializable> implements Set<T>, Serializable
} }
/** /**
* @return The false posetive probability of the current state of the filter * @return The false positive probability of the current state of the filter
*/ */
public double falsePosetiveProbability(){ public double falsePosetiveProbability(){
return Math.pow(0.6185, bits.size()/content_size); return Math.pow(0.6185, bits.size()/content_size);

View file

@ -20,18 +20,21 @@ import javax.swing.JLabel;
import zutil.ProgressListener; import zutil.ProgressListener;
import zutil.image.ImageFilterProcessor; import zutil.image.ImageFilterProcessor;
import zutil.image.filters.GaussianBlurFilter;
import zutil.image.filters.BlurFilter; import zutil.image.filters.BlurFilter;
import zutil.image.filters.ColorIntensityFilter; import zutil.image.filters.ColorIntensityFilter;
import zutil.image.filters.ContrastBrightnessFilter; import zutil.image.filters.ContrastBrightnessFilter;
import zutil.image.filters.DitheringFilter; import zutil.image.filters.DitheringFilter;
import zutil.image.filters.FaceDetectionFilter; import zutil.image.filters.MeanBlurFilter;
import zutil.image.filters.MedianFilter; import zutil.image.filters.MedianFilter;
import zutil.image.filters.ResizeImage; import zutil.image.filters.ResizeImage;
import zutil.image.filters.SobelEdgeDetectionFilter;
import zutil.image.filters.SpotLightFilter; import zutil.image.filters.SpotLightFilter;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public class ImageProcessorTest implements ProgressListener{ public class ImageProcessorTest implements ProgressListener{
private static String imgPath = "exemple.gif"; private static String imgPath = "test.gif";
//private static String imgPath = "test2.jpg";
private JLabel processedLabel; private JLabel processedLabel;
private JLabel orginalLabel; private JLabel orginalLabel;
@ -61,14 +64,16 @@ public class ImageProcessorTest implements ProgressListener{
BufferedImage procImg = null; BufferedImage procImg = null;
try { try {
//ImageFilterProcessor processor = new BlurFilter(img, 10); //ImageFilterProcessor processor = new SobelEdgeDetectionFilter(img);
ImageFilterProcessor processor = new GaussianBlurFilter(img);
//ImageFilterProcessor processor = new BlurFilter(img, 100);
//ImageFilterProcessor processor = new ColorIntensityFilter(img, true); //ImageFilterProcessor processor = new ColorIntensityFilter(img, true);
//ImageFilterProcessor processor = new ContrastBrightnessFilter(img); //ImageFilterProcessor processor = new ContrastBrightnessFilter(img);
ImageFilterProcessor processor = new DitheringFilter(img); //ImageFilterProcessor processor = new DitheringFilter(img);
//ImageFilterProcessor processor = new MeanBlurFilter(img);
//ImageFilterProcessor processor = new MedianFilter(img); //ImageFilterProcessor processor = new MedianFilter(img);
//ImageFilterProcessor processor = new ResizeImage(img,100,100); //ImageFilterProcessor processor = new ResizeImage(img,100,100);
//ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100); //ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100);
//ImageFilterProcessor processor = new FaceDetectionFilter(img);
processor.setProgressListener(this); processor.setProgressListener(this);
procImg = processor.process(); procImg = processor.process();

View file

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Before After
Before After

BIN
test2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB