3/5/12

Background light change compensation

Today I've toyed with idea of background light change compensation, and did some bugfixes to ImageProcessor class.


Source code:

import java.awt.Color;
import java.awt.image.BufferedImage;

public class ImageProcessor {
public int[][] getColorArray(final BufferedImage img) {
assert img != null;

final int width = img.getWidth();
final int height = img.getHeight();

final int[][] result = new int[width][height];

for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
result[i][j] = img.getRGB(i, j);
}
}

return result;
}

public int[][] getGrayscaleArray(final BufferedImage img) {
assert img != null;

final int width = img.getWidth();
final int height = img.getHeight();

final int[][] result = new int[width][height];

for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int color = img.getRGB(i, j);

int red = (color & 0x00ff0000) >> 16;
int green = (color & 0x0000ff00) >> 8;
int blue = color & 0x000000ff;
int avgGray = (red + green + blue) / 3;
Color grayColor = new Color(avgGray, avgGray, avgGray);

result[i][j] = grayColor.getRGB();
}
}

return result;
}

public int[][] applyCompensateBackgroundLightChangeFilter(final int[][] grayscaleToCompensate, final int[][] grayscaleToCompensateWith, final int iterations) {
int[][] result = grayscaleToCompensate;
for (int i=0; i<iterations; i++) {
int averageGray1 = getAverageGrayscaleValue(result);
int averageGray2 = getAverageGrayscaleValue(grayscaleToCompensateWith);
int averageGrayDifference = averageGray1 - averageGray2;
result = compensateLightDifference(result, averageGrayDifference);
}
return result;
}

public int[][] applyDifferenceFilter(final int[][] colorArray1, final int[][] colorArray2) {
assert colorArray1 != null;
assert colorArray2 != null;
assert colorArray1.length > 0;
assert colorArray2.length > 0;
assert colorArray1.length == colorArray2.length;
assert colorArray1[0].length == colorArray2[0].length;

final int width = colorArray1.length;
final int height = colorArray1[0].length;

final int[][] result = new int[width][height];

for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int color1 = colorArray1[i][j];
int color2 = colorArray2[i][j];

int red1 = (color1 & 0x00ff0000) >> 16;
int red2 = (color2 & 0x00ff0000) >> 16;

int green1 = (color1 & 0x0000ff00) >> 8;
int green2 = (color2 & 0x0000ff00) >> 8;

int blue1 = color1 & 0x000000ff;
int blue2 = color2 & 0x000000ff;

result[i][j] = new Color(
Math.abs(red1 - red2), Math.abs(green1 - green2), Math.abs(blue1 - blue2)).getRGB();
}
}

return result;
}

public int[][] applyThresholdFilter(int[][] colorArray, int threshold) {
final int width = colorArray.length;
final int height = colorArray[0].length;

final int[][] result = new int[width][height];

for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int color = colorArray[i][j];
int red = (color & 0x00ff0000) >> 16;
int green = (color & 0x0000ff00) >> 8;
int blue = color & 0x000000ff;
int avgGray = (red + green + blue) / 3;

result[i][j] = avgGray > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}
}

return result;
}

/**
* @param colorArray
* @param threshold number of neighboring white pixels needed to retain visibility of pixel
* @return
*/
public int[][] applyErosionFilter(int[][] grayscaleArray, int threshold) {
final int width = grayscaleArray.length;
final int height = grayscaleArray[0].length;

final int[][] result = new int[width][height];

// interior
for (int i = 1; i < width-1; i++) {
for (int j = 1; j < height-1; j++) {
int color = grayscaleArray[i][j];

if (color != Color.WHITE.getRGB()) { // check only white pixels
result[i][j] = Color.BLACK.getRGB();
continue;
}

int whiteNeighborPixelCount = 0;

whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i-1][j-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i][j-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i+1][j-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i-1][j]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i+1][j]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i-1][j+1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i][j+1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i+1][j+1]);

result[i][j] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}
}

// borders
for (int i=1; i<width-1; i++) {
int upperBorderColor = grayscaleArray[i][0];

if (upperBorderColor != Color.WHITE.getRGB()) { // check only white pixels
result[i][0] = Color.BLACK.getRGB();
continue;
}

int whiteNeighborPixelCount = 3;

whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i-1][0]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i+1][0]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i-1][1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i][1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i+1][1]);

result[i][0] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}

for (int i=1; i<width-1; i++) {
int lowerBorderColor = grayscaleArray[i][height-1];

if (lowerBorderColor != Color.WHITE.getRGB()) { // check only white pixels
result[i][height-1] = Color.BLACK.getRGB();
continue;
}

int whiteNeighborPixelCount = 3;

whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i-1][height-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i+1][height-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i-1][height-2]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i][height-2]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[i+1][height-2]);

result[i][height-1] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}

for (int j=1; j<height-1; j++) {
int leftBorderColor = grayscaleArray[0][j];

if (leftBorderColor != Color.WHITE.getRGB()) { // check only white pixels
result[0][j] = Color.BLACK.getRGB();
continue;
}

int whiteNeighborPixelCount = 3;

whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[0][j-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[0][j+1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[1][j-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[1][j]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[1][j+1]);

result[0][j] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}

for (int j=1; j<height-1; j++) {
int rightBorderColor = grayscaleArray[0][j];

if (rightBorderColor != Color.WHITE.getRGB()) { // check only white pixels
result[width-1][j] = Color.BLACK.getRGB();
continue;
}

int whiteNeighborPixelCount = 3;

whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-1][j-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-1][j+1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-2][j-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-2][j-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-2][j+1]);

result[width-1][j] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}

// corners
int upperLeftColor = grayscaleArray[0][0];
if (upperLeftColor != Color.WHITE.getRGB()) { // check only white pixels
result[0][0] = Color.BLACK.getRGB();
} else {
int whiteNeighborPixelCount = 5;
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[0][1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[1][1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[1][0]);

result[0][0] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}

int upperRightColor = grayscaleArray[width-1][0];
if (upperRightColor != Color.WHITE.getRGB()) { // check only white pixels
result[width-1][0] = Color.BLACK.getRGB();
} else {
int whiteNeighborPixelCount = 5;
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-1][0]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-2][1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-2][0]);

result[width-1][0] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}

int lowerLeftColor = grayscaleArray[0][height-1];
if (lowerLeftColor != Color.WHITE.getRGB()) { // check only white pixels
result[0][height-1] = Color.BLACK.getRGB();
} else {
int whiteNeighborPixelCount = 5;
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[0][height-2]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[1][height-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[1][height-2]);

result[0][height-1] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}

int lowerRightColor = grayscaleArray[width-1][height-1];
if (lowerRightColor != Color.WHITE.getRGB()) { // check only white pixels
result[width-1][height-1] = Color.BLACK.getRGB();
} else {
int whiteNeighborPixelCount = 5;
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-1][height-2]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-2][height-1]);
whiteNeighborPixelCount = adjustWhiteNeighborPixelCount(whiteNeighborPixelCount, grayscaleArray[width-2][height-2]);

result[width-1][height-1] = whiteNeighborPixelCount > threshold ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
}

return result;
}

public final int countMovementMagnitude(int[][] erodedBlackAndWhiteArray) {
final int width = erodedBlackAndWhiteArray.length;
final int height = erodedBlackAndWhiteArray[0].length;

int result = 0;

for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int color = erodedBlackAndWhiteArray[i][j];

if (color == Color.WHITE.getRGB()) {
result = result + 1;
}
}
}

return result;
}


public BufferedImage getImage(final int width, final int height, final int[][] colorArray) {
assert width > 0;
assert height > 0;
assert colorArray != null;

final BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

for (int i=0; i<width; i++) {
for (int j=0; j<height; j++) {
result.setRGB(i, j, colorArray[i][j]);
}
}

return result;
}

/**
* @param grayscaleArray reference image.
* At each pixel, color samples adhere to rule:
* image(x,y).getRed == pixel(x,y).getGreen == pixel(x,y).getBlue
* @return
*/
public int getAverageGrayscaleValue(int[][] grayscaleArray) {
assert grayscaleArray != null;

final int width = grayscaleArray.length;
final int height = grayscaleArray[0].length;

long averageGrayscaleValue = 0;

for (int i=0; i<width; i++) {
for (int j=0; j<height; j++) {
int red = new Color(grayscaleArray[i][j]).getRed();
int green = new Color(grayscaleArray[i][j]).getGreen();
int blue = new Color(grayscaleArray[i][j]).getBlue();
if (red != green || green != blue) throw new IllegalArgumentException("red != green || green != blue");

averageGrayscaleValue = averageGrayscaleValue + green;
}
}

averageGrayscaleValue = averageGrayscaleValue / (width*height);
return (int) averageGrayscaleValue;
}

public int[][] compensateLightDifference(int[][] grayscaleArray, int lightDifference) {
assert grayscaleArray != null;

final int width = grayscaleArray.length;
final int height = grayscaleArray[0].length;

int[][] result = new int[width][height];

for (int i=0; i<width; i++) {
for (int j=0; j<height; j++) {
int red = new Color(grayscaleArray[i][j]).getRed();
int green = new Color(grayscaleArray[i][j]).getGreen();
int blue = new Color(grayscaleArray[i][j]).getBlue();
if (red != green || green != blue) throw new IllegalArgumentException("red != green || green != blue");

int compensatedValue = green - lightDifference;

if (compensatedValue > 255) {
compensatedValue = 255;
}

if (compensatedValue < 0) {
compensatedValue = 0;
}

result[i][j] = new Color(compensatedValue, compensatedValue, compensatedValue).getRGB();
}
}

return result;
}


/**
* @param whiteNeighborPixelCount initial whiteNeighborPixelCount
* @param neighborPixelColor color of neighbor pixel to check
* @return adjusted white neighbor pixel count
*/
private int adjustWhiteNeighborPixelCount(final int whiteNeighborPixelCount, int neighborPixelColor) {
return neighborPixelColor == Color.WHITE.getRGB() ? whiteNeighborPixelCount + 1 : whiteNeighborPixelCount;
}

}


No comments:

Post a Comment