Added new filters and remove face detection(it didn't work)
This commit is contained in:
parent
41c474d2a5
commit
73be002969
18 changed files with 497 additions and 362 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
83
src/zutil/image/filters/ConvolutionFilter.java
Normal file
83
src/zutil/image/filters/ConvolutionFilter.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
47
src/zutil/image/filters/GaussianBlurFilter.java
Normal file
47
src/zutil/image/filters/GaussianBlurFilter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
45
src/zutil/image/filters/MeanBlurFilter.java
Normal file
45
src/zutil/image/filters/MeanBlurFilter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
64
src/zutil/image/filters/SobelEdgeDetectionFilter.java
Normal file
64
src/zutil/image/filters/SobelEdgeDetectionFilter.java
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
BIN
test2.jpg
Normal file
BIN
test2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 99 KiB |
Loading…
Add table
Add a link
Reference in a new issue