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
* @param listener The listener, null to disable the progress
* @param listener is the listener, null to disable the progress
*/
public void setProgressListener(ProgressListener listener){
this.progress = listener;
}
/**
* Returns the listener
*/
public ProgressListener getProgressListener(){
return this.progress;
}
/**
* Sets the progress in percent
*/
@ -65,23 +72,23 @@ public abstract class ImageFilterProcessor {
// converts the img to raw data
int[][][] data = convertToArray(img, cols, rows);
//processes the image
process(data);
data = process(data);
//converts back the image
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]
* 0 -> Alpha data
* Red data
* Green data
* 4 -> Blue data
*
* @param img The image to convert
* @param cols Columns of the image
* @param rows Rows of the image
* @return A Integer array
* @param img is the image to convert
* @param cols is the columns of the image
* @param rows is the rows of the image
* @return A is the integer array
* @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
for(int x=0; x<cols ;x++){
//Alpha data
data[y][x][0] = (aRow[x] >> 24) & 0xFF;
data[y][x][0] = ((aRow[x] >> 24) & 0xFF);
//Red data
data[y][x][1] = (aRow[x] >> 16) & 0xFF;
data[y][x][1] = ((aRow[x] >> 16) & 0xFF);
//Green data
data[y][x][2] = (aRow[x] >> 8) & 0xFF;
data[y][x][2] = ((aRow[x] >> 8) & 0xFF);
//Blue data
data[y][x][3] = (aRow[x])& 0xFF;
data[y][x][3] = ((aRow[x])& 0xFF);
}
}
return data;
@ -117,9 +124,9 @@ public abstract class ImageFilterProcessor {
/**
* Converts a pixel data array to a java Image object
*
* @param pixels The pixel data array
* @param cols Columns of the image
* @param rows Rows of the image
* @param pixels is the pixel data array
* @param cols is the columns of the image
* @param rows is the rows of the image
* @return A Image
*/
public static BufferedImage convertToImage(int[][][] pixels, int cols, int rows){
@ -148,20 +155,22 @@ public abstract class ImageFilterProcessor {
}
/**
* Runs the image thrue the processor
* @param data The raw image to apply the effect to
* Runs the image thru the processor
* @param data is the raw image to apply the effect to. This will NOT be altered
*/
public void process(final int[][][] data){
process(data, 0, 0, data[0].length, data.length);
public int[][][] process(int[][][] data){
return process(data, 0, 0, data[0].length, data.length);
}
/**
* 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 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 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
* @return The peak value of the image
*/
public static int peakValue(int[][][] data) {
return peakValue(data, 0, 0, data[0].length, data.length);
public static int getPeakValue(int[][][] data) {
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
* @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;
for(int y=startY; y<stopY ;y++){
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
* @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;
long accum = 0;
for(int y=startY; y <stopY ;y++){
@ -114,12 +114,12 @@ public class ImageUtil {
/**
* 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 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 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){
for(int y=startY; y<stopY ;y++){
@ -134,54 +134,114 @@ public class ImageUtil {
/**
* Returns the mean value of the given image data
*
* @param data The image data
* @return The mean value of the image
* @param data is the image data
* @return the mean value of the image
*/
public static int meanValue(int[][][] data){
return meanValue(data, 0, 0, data[0].length, data.length);
public static int getMeanValue(int[][][] data){
return getMeanValue(data, 0, 0, data[0].length, data.length);
}
/**
* 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 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
* @return the mean value of the image
*/
public static int meanValue(int[][][] data, int startX, int startY, int stopX, int stopY){
int pixelCount = 0;
long accum = 0;
public static int getMeanValue(int[][][] data, int startX, int startY, int stopX, int stopY){
int[] tmp = getMeanArray(data, startX, startY, stopX, stopY);
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 x=startX; x<stopX ;x++){
accum += data[y][x][1];
accum += data[y][x][2];
accum += data[y][x][3];
pixelCount += 3;
mean[0] += data[y][x][1];
mean[1] += data[y][x][2];
mean[2] += data[y][x][3];
}
}
// 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;
}
/**
* Adds the mean value to the image data
* removes the mean value from 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 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 The mean value
* @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
*
* @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 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 x=startX; x<stopX ;x++){
data[y][x][1] += mean;
data[y][x][2] += mean;
data[y][x][3] += mean;
data[y][x][1] += mean[0];
data[y][x][2] += mean[1];
data[y][x][3] += mean[2];
}
}
}
@ -309,5 +369,4 @@ public class ImageUtil {
else
return color;
}
}

View file

@ -28,10 +28,11 @@ public class BlurFilter extends ImageFilterProcessor{
}
@Override
public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
int inputPeak = ImageUtil.peakValue(data);
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int inputPeak = ImageUtil.getPeakValue(data);
int[][][] tmpData = new int[data.length][data[0].length][4];
int[][][] output = ImageUtil.copyArray(data);
//Perform the convolution one or more times in succession
int redSum, greenSum, blueSum, outputPeak;
for(int i=0; i<blurValue ;i++){
@ -39,44 +40,44 @@ public class BlurFilter extends ImageFilterProcessor{
for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, (blurValue-1)*(stopY-startY-2), i*(stopY-startY-2)+y));
for(int x=startX; x<stopX ;x++){
if(x == 0 || x == data[0].length-1 || y == 0 || y == data.length-1){
redSum = data[y][x][1] * 9;
greenSum = data[y][x][2] * 9;
blueSum = data[y][x][3] * 9;
if(x == 0 || x == output[0].length-1 || y == 0 || y == output.length-1){
redSum = output[y][x][1] * 9;
greenSum = output[y][x][2] * 9;
blueSum = output[y][x][3] * 9;
}
else{
redSum =
data[y - 1][x - 1][1] +
data[y - 1][x - 0][1] +
data[y - 1][x + 1][1] +
data[y - 0][x - 1][1] +
data[y - 0][x - 0][1] +
data[y - 0][x + 1][1] +
data[y + 1][x - 1][1] +
data[y + 1][x - 0][1] +
data[y + 1][x + 1][1];
output[y - 1][x - 1][1] +
output[y - 1][x - 0][1] +
output[y - 1][x + 1][1] +
output[y - 0][x - 1][1] +
output[y - 0][x - 0][1] +
output[y - 0][x + 1][1] +
output[y + 1][x - 1][1] +
output[y + 1][x - 0][1] +
output[y + 1][x + 1][1];
greenSum =
data[y - 1][x - 1][2] +
data[y - 1][x - 0][2] +
data[y - 1][x + 1][2] +
data[y - 0][x - 1][2] +
data[y - 0][x - 0][2] +
data[y - 0][x + 1][2] +
data[y + 1][x - 1][2] +
data[y + 1][x - 0][2] +
data[y + 1][x + 1][2];
output[y - 1][x - 1][2] +
output[y - 1][x - 0][2] +
output[y - 1][x + 1][2] +
output[y - 0][x - 1][2] +
output[y - 0][x - 0][2] +
output[y - 0][x + 1][2] +
output[y + 1][x - 1][2] +
output[y + 1][x - 0][2] +
output[y + 1][x + 1][2];
blueSum =
data[y - 1][x - 1][3] +
data[y - 1][x - 0][3] +
data[y - 1][x + 1][3] +
data[y - 0][x - 1][3] +
data[y - 0][x - 0][3] +
data[y - 0][x + 1][3] +
data[y + 1][x - 1][3] +
data[y + 1][x - 0][3] +
data[y + 1][x + 1][3];
output[y - 1][x - 1][3] +
output[y - 1][x - 0][3] +
output[y - 1][x + 1][3] +
output[y - 0][x - 1][3] +
output[y - 0][x - 0][3] +
output[y - 0][x + 1][3] +
output[y + 1][x - 1][3] +
output[y + 1][x - 0][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][2] = greenSum;
tmpData[y][x][3] = blueSum;
@ -84,8 +85,9 @@ public class BlurFilter extends ImageFilterProcessor{
}
// getting the new peak value and normalizing the image
outputPeak = ImageUtil.peakValue(tmpData);
ImageUtil.normalize(data, tmpData, startX, startY, stopX, stopY, ((double)inputPeak)/outputPeak );
}
outputPeak = ImageUtil.getPeakValue(tmpData);
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{
private boolean invert;
private int redScale;
private int greenScale;
private int blueScale;
private double redScale;
private double greenScale;
private double blueScale;
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
*/
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
* @param img The image data
* @param red The scale of red (0-100)
* @param green The scale of green (0-100)
* @param blue The scale of blue (0-100)
* @param red The scale of red (0-1)
* @param green The scale of green (0-1)
* @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);
}
/**
* Creates a ColorIntensityEffect object with the given values
* @param img The image data
* @param red The scale of red (0-100)
* @param green The scale of green (0-100)
* @param blue The scale of blue (0-100)
* @param red The scale of red (0-1)
* @param green The scale of green (0-1)
* @param blue The scale of blue (0-1)
* @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);
invert = false;
redScale = red;
@ -52,15 +52,16 @@ public class ColorIntensityFilter extends ImageFilterProcessor{
}
@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
if(redScale > 100) redScale = 100;
if(redScale > 1) redScale = 1;
else if(redScale < 0) redScale = 0;
if(greenScale > 100) greenScale = 100;
if(greenScale > 1) greenScale = 1;
else if(greenScale < 0) greenScale = 0;
if(blueScale > 100) blueScale = 100;
if(blueScale > 1) blueScale = 1;
else if(blueScale < 0) blueScale = 0;
// Applying the color intensity to the image
@ -69,19 +70,20 @@ public class ColorIntensityFilter extends ImageFilterProcessor{
for(int x=startX; x<stopX ;x++){
if(!invert){
// inversion
data[y][x][0] = data[y][x][0];
data[y][x][1] = 255 - data[y][x][1] * redScale/100;
data[y][x][2] = 255 - data[y][x][2] * greenScale/100;
data[y][x][3] = 255 - data[y][x][3] * blueScale/100;
output[y][x][0] = data[y][x][0];
output[y][x][1] = (int)( 255 - data[y][x][1] * redScale );
output[y][x][2] = (int)( 255 - data[y][x][2] * greenScale );
output[y][x][3] = (int)( 255 - data[y][x][3] * blueScale );
}
else{
data[y][x][0] = data[y][x][0];
data[y][x][1] = data[y][x][1] * redScale/100;
data[y][x][2] = data[y][x][2] * greenScale/100;
data[y][x][3] = data[y][x][3] * blueScale/100;
output[y][x][0] = data[y][x][0];
output[y][x][1] = (int)( data[y][x][1] * redScale );
output[y][x][2] = (int)( data[y][x][2] * greenScale );
output[y][x][3] = (int)( data[y][x][3] * blueScale );
}
}
}
return output;
}
}

View file

@ -30,14 +30,18 @@ public class ContrastBrightnessFilter extends ImageFilterProcessor{
}
@Override
public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
int mean = ImageUtil.meanValue(data);
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int mean = ImageUtil.getMeanValue(data);
ImageUtil.addMeanValue(data, startX, startY, stopX, stopY, mean*(-1));
ImageUtil.scale(data, startX, startY, stopX, stopY, contrast);
ImageUtil.addMeanValue(data, startX, startY, stopX, stopY, (int)(brightness*mean));
int[][][] output = ImageUtil.copyArray(data);
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(data , startX, startY, stopX, stopY);
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
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[] currentPixel;
int[][][] output = ImageUtil.copyArray(data);
for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, stopY-startY-1, y));
for(int x=startX; x<stopX ;x++){
currentPixel = data[y][x];
currentPixel = output[y][x];
index = findNearestColor(currentPixel, palette);
data[y][x] = palette[index];
output[y][x] = palette[index];
for (int i = 1; i < 4; i++) {
error = currentPixel[i] - palette[index][i];
if (x + 1 < data[0].length) {
data[y+0][x+1][i] = ImageUtil.clip( data[y+0][x+1][i] + (error*7)/16 );
if (x + 1 < output[0].length) {
output[y+0][x+1][i] = ImageUtil.clip( output[y+0][x+1][i] + (error*7)/16 );
}
if (y + 1 < data.length) {
if (x - 1 > 0)
data[y+1][x-1][i] = ImageUtil.clip( data[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-1][i] = ImageUtil.clip( output[y+1][x-1][i] + (error*3)/16 );
output[y+1][x+0][i] = ImageUtil.clip( output[y+1][x+0][i] + (error*5)/16 );
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) {

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

@ -34,7 +34,7 @@ public class MedianFilter extends ImageFilterProcessor{
public MedianFilter(BufferedImage img, int pixels) {
this(img, pixels, new boolean[]{true,true,true,true});
}
/**
* Setup a default MedianFilter
*
@ -49,36 +49,36 @@ public class MedianFilter extends ImageFilterProcessor{
}
/*
edgex := (window width / 2) rounded down
edgey := (window height / 2) rounded down
for x from edgex to image width - edgex:
for y from edgey to image height - edgey:
colorArray[window width][window height];
for fx from 0 to window width:
for fy from 0 to window height:
colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
Sort colorArray[][];
pixelValue[x][y] := colorArray[window width / 2][window height / 2];
edgex := (window width / 2) rounded down
edgey := (window height / 2) rounded down
for x from edgex to image width - edgex:
for y from edgey to image height - edgey:
colorArray[window width][window height];
for fx from 0 to window width:
for fy from 0 to window height:
colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
Sort colorArray[][];
pixelValue[x][y] := colorArray[window width / 2][window height / 2];
*/
@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 edgeX = windowSize / 2;
int edgeY = windowSize / 2;
int[][] tmpArray = new int[4][256*2];
int pixelCount = 0;
for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, stopY-startY-1, y));
for(int x=startX; x<stopX ;x++){
pixelCount = 0;
for(int fy=0; fy<windowSize ;fy++){
for(int fx=0; fx<windowSize ;fx++){
if(y+fy-edgeY >= 0 && y+fy-edgeY < data.length && x+fx-edgeX >= 0 && x+fx-edgeX < data[0].length){
//colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
if(channels[0]) tmpArray[0][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][0] ) ]++;
if(channels[0]) tmpArray[0][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][0] ) ]++;
if(channels[1]) tmpArray[1][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][1] ) ]++;
if(channels[2]) tmpArray[2][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][2] ) ]++;
if(channels[3]) tmpArray[3][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][3] ) ]++;
@ -87,23 +87,21 @@ public class MedianFilter extends ImageFilterProcessor{
}
}
if(channels[0]) data[y][x][0] = findMedian(tmpArray[0], pixelCount/2);
else data[y][x][0] = tmpData[y][x][0];
if(channels[1]) data[y][x][1] = findMedian(tmpArray[1], pixelCount/2);
else data[y][x][1] = tmpData[y][x][1];
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];
if(channels[0]) tmpData[y][x][0] = findMedian(tmpArray[0], pixelCount/2);
if(channels[1]) tmpData[y][x][1] = findMedian(tmpArray[1], pixelCount/2);
if(channels[2]) tmpData[y][x][2] = findMedian(tmpArray[2], pixelCount/2);
if(channels[3]) tmpData[y][x][3] = findMedian(tmpArray[3], pixelCount/2);
}
}
return tmpData;
}
private int getMedianIndex(int i){
if(i < 0) return Math.abs(i);
else return i+256;
}
private int findMedian(int[] median, int medianCount){
int sum = 0;
int ret = 0;
@ -114,11 +112,11 @@ public class MedianFilter extends ImageFilterProcessor{
ret = i-256;
}
}
return ret;
}
class SortableARGB implements SortableDataList<Integer>{
private int[][][] data;
private int cols;
@ -153,12 +151,12 @@ public class MedianFilter extends ImageFilterProcessor{
data[ getY(a) ][ getX(a) ][ channel ] = data[ getY(b) ][ getX(b) ][ channel ];
data[ getY(b) ][ getX(b) ][ channel ] = tmp;
}
private int getX(int a){
return a % cols;
}
private int getY(int a){
return a / cols;
}

View file

@ -3,7 +3,6 @@ package zutil.image.filters;
import java.awt.image.BufferedImage;
import zutil.image.ImageFilterProcessor;
import zutil.image.ImageUtil;
import zutil.math.ZMath;
public class ResizeImage extends ImageFilterProcessor{
@ -37,7 +36,7 @@ public class ResizeImage extends ImageFilterProcessor{
}
@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){
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;
}
}

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
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(yPos < 0) yPos = data.length/2;
int[][][] output = new int[data.length][data[0].length][4];
double scale, dx, dy, distance;
for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, (stopY-startY)-1, y));
@ -61,12 +63,13 @@ public class SpotLightFilter extends ImageFilterProcessor{
scale = 1-(distance/radius);
}
data[y][x][0] = data[y][x][0];
data[y][x][1] = ImageUtil.clip((int)(scale * data[y][x][1]));
data[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][0] = data[y][x][0];
output[y][x][1] = ImageUtil.clip((int)(scale * data[y][x][1]));
output[y][x][2] = ImageUtil.clip((int)(scale * data[y][x][2]));
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
* @return If the object contains in the filter or false
* if the Object is not Serializable
* @param o is the Serializable object to search for
* @return If the object contains in the filter or
* false if the Object is not Serializable
*/
public boolean contains(Object o) {
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(){
return Math.pow(0.6185, bits.size()/content_size);

View file

@ -20,18 +20,21 @@ import javax.swing.JLabel;
import zutil.ProgressListener;
import zutil.image.ImageFilterProcessor;
import zutil.image.filters.GaussianBlurFilter;
import zutil.image.filters.BlurFilter;
import zutil.image.filters.ColorIntensityFilter;
import zutil.image.filters.ContrastBrightnessFilter;
import zutil.image.filters.DitheringFilter;
import zutil.image.filters.FaceDetectionFilter;
import zutil.image.filters.MeanBlurFilter;
import zutil.image.filters.MedianFilter;
import zutil.image.filters.ResizeImage;
import zutil.image.filters.SobelEdgeDetectionFilter;
import zutil.image.filters.SpotLightFilter;
@SuppressWarnings("unused")
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 orginalLabel;
@ -61,14 +64,16 @@ public class ImageProcessorTest implements ProgressListener{
BufferedImage procImg = null;
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 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 ResizeImage(img,100,100);
//ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100);
//ImageFilterProcessor processor = new FaceDetectionFilter(img);
//ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100);
processor.setProgressListener(this);
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