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