Implemented a part of SideScanner and added ImageScanner: scans a single

image
This commit is contained in:
Paul Schaller 2023-11-18 15:23:16 +01:00
parent b750ae9344
commit b3031ad97f
3 changed files with 189 additions and 84 deletions

View File

@ -10,89 +10,6 @@ import java.util.List;
import com.cringe_studios.christmastreescanning.Point3D;
public class ChristmasTreeScanning {
//TODO maybe use Point2D.Double as return type, so the Points don't have to be converted to Points2D later down the pipeline during the normalization step
private Point getBrightestSpotGrayscale(BufferedImage grayScaleImage, byte gammaDelta) {
int[] imageColors = grayScaleImage.getRGB(0, 0, grayScaleImage.getWidth(), grayScaleImage.getHeight(), null, 0, 0);
for(int i = 0; i < imageColors.length; i++) {
imageColors[i] &= 0x0000_00FF; // because the image is grayscale, only one component is needed
}
int brightestValue = 0;
for(int i = 0; i < imageColors.length; i++) {
if(brightestValue < imageColors[i]) {
brightestValue = imageColors[i];
}
}
List<Integer> brightSpots = new ArrayList<Integer>();
for(int i = 0; i < imageColors.length; i++) {
if(imageColors[i] >= brightestValue - gammaDelta) {
brightSpots.add(Integer.valueOf(i));
}
}
//The following line might be incorrect; TODO double check and write a test
Point brightPoints[] = brightSpots.stream().map(s -> new Point(s.intValue() % grayScaleImage.getWidth(), s.intValue() / grayScaleImage.getWidth())).toArray(Point[]::new);
Point brightestSpot = new PointInterpolator(brightPoints).getCenter();
return brightestSpot;
}
//gammaDelta is the difference between the brightest pixel and the darkest pixel included in the search set for the brightest spot
//The brightest point Operation is done per color dimension, so you could provide different images for red, green and blue brightest points
public Point getBrightestSpot(BufferedImage redImage, BufferedImage greenImage, BufferedImage blueImage, byte gammaDelta) {
Point brightestRedSpot = getBrightestSpotGrayscale(redImage, gammaDelta);
Point brightestGreenSpot = getBrightestSpotGrayscale(greenImage, gammaDelta);
Point brightestBlueSpot = getBrightestSpotGrayscale(blueImage, gammaDelta);
double RGdistance = brightestRedSpot.distanceSq(brightestGreenSpot);
double GBdistance = brightestGreenSpot.distanceSq(brightestBlueSpot);
double BRdistance = brightestBlueSpot.distanceSq(brightestRedSpot);
PointInterpolator brightestSpot;
//Get the center between the two closest points; a better implementation would work with a confidentnes-value
if(RGdistance < GBdistance && RGdistance < BRdistance) {
brightestSpot = new PointInterpolator(brightestRedSpot, brightestGreenSpot);
}else if(GBdistance < RGdistance && GBdistance < BRdistance) {
brightestSpot = new PointInterpolator(brightestGreenSpot, brightestBlueSpot);
}else {
brightestSpot = new PointInterpolator(brightestBlueSpot, brightestRedSpot);
}
return brightestSpot.getCenter();
}
public Point getBrightestSpot(BufferedImage image, byte gammaDelta) {
BufferedImage redImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
BufferedImage greenImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
BufferedImage blueImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
for(int i = 0; i < image.getWidth(); i++) {
for(int j = 0; j < image.getHeight(); j++) {
int currentRGB = image.getRGB(i, j);
int currentBlue = currentRGB & 0xFF;
int currentGreen = (currentRGB >> 8) & 0xFF;
int currentRed = (currentRGB >> 16) & 0xFF;
redImage.setRGB(i, j, (currentRed << 16) | (currentRed << 8) | currentRed);
greenImage.setRGB(i, j, (currentGreen << 16) | (currentGreen << 8) | currentGreen);
blueImage.setRGB(i, j, (currentBlue << 16) | (currentBlue << 8) | currentBlue);
}
}
return getBrightestSpot(redImage, greenImage, blueImage, gammaDelta);
}
public Point getBrightestSpot(BufferedImage image) {
return getBrightestSpot(image, (byte)0);
}
// This method normalizes the Point coordinates,

View File

@ -0,0 +1,98 @@
package com.cringe_studios.christmastreescanning.scanning;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
public class ImageScanner {
public static final byte GAMMA_DELTA_DEFAULT = 0;
// TODO maybe use Point2D.Double as return type, so the Points don't have to be
// converted to Points2D later down the pipeline during the normalization step
static private Point getBrightestSpotGrayscale(BufferedImage grayScaleImage, byte gammaDelta) {
int[] imageColors = grayScaleImage.getRGB(0, 0, grayScaleImage.getWidth(), grayScaleImage.getHeight(), null, 0, 0);
for (int i = 0; i < imageColors.length; i++) {
imageColors[i] &= 0x0000_00FF; // because the image is grayscale, only one component is needed
}
int brightestValue = 0;
for (int i = 0; i < imageColors.length; i++) {
if (brightestValue < imageColors[i]) {
brightestValue = imageColors[i];
}
}
List<Integer> brightSpots = new ArrayList<Integer>();
for (int i = 0; i < imageColors.length; i++) {
if (imageColors[i] >= brightestValue - gammaDelta) {
brightSpots.add(Integer.valueOf(i));
}
}
// The following line might be incorrect; TODO double check and write a test
Point brightPoints[] = brightSpots.stream()
.map(s -> new Point(s.intValue() % grayScaleImage.getWidth(), s.intValue() / grayScaleImage.getWidth()))
.toArray(Point[]::new);
Point brightestSpot = new PointInterpolator(brightPoints).getCenter();
return brightestSpot;
}
// gammaDelta is the difference between the brightest pixel and the darkest
// pixel included in the search set for the brightest spot
// The brightest point Operation is done per color dimension, so you could
// provide different images for red, green and blue brightest points
static public Point getBrightestSpot(BufferedImage redImage, BufferedImage greenImage, BufferedImage blueImage,
byte gammaDelta) {
Point brightestRedSpot = getBrightestSpotGrayscale(redImage, gammaDelta);
Point brightestGreenSpot = getBrightestSpotGrayscale(greenImage, gammaDelta);
Point brightestBlueSpot = getBrightestSpotGrayscale(blueImage, gammaDelta);
double RGdistance = brightestRedSpot.distanceSq(brightestGreenSpot);
double GBdistance = brightestGreenSpot.distanceSq(brightestBlueSpot);
double BRdistance = brightestBlueSpot.distanceSq(brightestRedSpot);
PointInterpolator brightestSpot;
// Get the center between the two closest points; a better implementation would
// work with a confidentnes-value
if (RGdistance < GBdistance && RGdistance < BRdistance) {
brightestSpot = new PointInterpolator(brightestRedSpot, brightestGreenSpot);
} else if (GBdistance < RGdistance && GBdistance < BRdistance) {
brightestSpot = new PointInterpolator(brightestGreenSpot, brightestBlueSpot);
} else {
brightestSpot = new PointInterpolator(brightestBlueSpot, brightestRedSpot);
}
return brightestSpot.getCenter();
}
static public Point getBrightestSpot(BufferedImage image, byte gammaDelta) {
BufferedImage redImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
BufferedImage greenImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
BufferedImage blueImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
int currentRGB = image.getRGB(i, j);
int currentBlue = currentRGB & 0xFF;
int currentGreen = (currentRGB >> 8) & 0xFF;
int currentRed = (currentRGB >> 16) & 0xFF;
redImage.setRGB(i, j, (currentRed << 16) | (currentRed << 8) | currentRed);
greenImage.setRGB(i, j, (currentGreen << 16) | (currentGreen << 8) | currentGreen);
blueImage.setRGB(i, j, (currentBlue << 16) | (currentBlue << 8) | currentBlue);
}
}
return getBrightestSpot(redImage, greenImage, blueImage, gammaDelta);
}
static public Point getBrightestSpot(BufferedImage image) {
return getBrightestSpot(image, GAMMA_DELTA_DEFAULT);
}
}

View File

@ -1,5 +1,95 @@
package com.cringe_studios.christmastreescanning.scanning;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
public class SideScanner {
private BufferedImage sideImages[];
private BufferedImage sideImagesRed[];
private BufferedImage sideImagesGreen[];
private BufferedImage sideImagesBlue[];
byte gammaDelta = ImageScanner.GAMMA_DELTA_DEFAULT;
double baseline = 0.0;
double minX = Double.NEGATIVE_INFINITY;
double maxX = Double.POSITIVE_INFINITY;
boolean useDefaultValues;
Point2D foundPoints[] = null;
public SideScanner(BufferedImage[] images, byte gammaDelta, double baseline, double minX, double maxX) {
this.sideImages = images;
this.gammaDelta = gammaDelta;
this.baseline = baseline;
this.minX = minX;
this.maxX = maxX;
this.useDefaultValues = false;
}
public SideScanner(BufferedImage[] imagesRed, BufferedImage[] imagesGreen, BufferedImage[] imagesBlue, byte gammaDelta, double baseline, double minX, double maxX) {
if(!(imagesRed.length == imagesGreen.length && imagesGreen.length == imagesBlue.length)); // TODO error
this.sideImagesRed = imagesRed;
this.sideImagesGreen = imagesGreen;
this.sideImagesBlue = imagesBlue;
this.gammaDelta = gammaDelta;
this.baseline = baseline;
this.minX = minX;
this.maxX = maxX;
this.useDefaultValues = false;
}
// Everything default values
public SideScanner(BufferedImage[] images) {
this.sideImages = images;
this.useDefaultValues = true;
}
public SideScanner(BufferedImage[] imagesRed, BufferedImage[] imagesGreen, BufferedImage[] imagesBlue) {
if(!(imagesRed.length == imagesGreen.length && imagesGreen.length == imagesBlue.length)); // TODO error
this.sideImagesRed = imagesRed;
this.sideImagesGreen = imagesGreen;
this.sideImagesBlue = imagesBlue;
this.useDefaultValues = true;
}
public void scan() {
int imagesLength = 0;
if(this.sideImages != null) {
imagesLength = this.sideImages.length;
}else {
imagesLength = this.sideImagesRed.length;
}
foundPoints = new Point2D[imagesLength];
for(int i = 0; i < imagesLength; i++) {
if(this.sideImages != null) {
if(this.useDefaultValues) {
foundPoints[i] = ImageScanner.getBrightestSpot(sideImages[i]);
}else {
foundPoints[i] = ImageScanner.getBrightestSpot(sideImages[i], this.gammaDelta);
}
}else {
foundPoints[i] = ImageScanner.getBrightestSpot(this.sideImagesRed[i], this.sideImagesGreen[i], this.sideImagesBlue[i], this.gammaDelta);
}
}
}
public Point2D[] getPoints() {
return foundPoints;
}
public void normalizePoints() {
if(foundPoints == null); //TODO error
//TODO
}
}