Added two helper Classes and partially implemented

This commit is contained in:
Paul Schaller 2023-11-14 15:51:36 +01:00
parent 81d25c6a2c
commit 9a9cbfd345
3 changed files with 169 additions and 4 deletions

View File

@ -1,18 +1,153 @@
package com.cringe_studios.christmastreescanning;
import java.awt.Color;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
public class ChristmasTreeScanning {
Point getBrightestSpot(BufferedImage image) {
int[] imageColors = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, 0);
public class ChristmasTreeScanning {
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
}
//TODO
Point brightestSpot = new Point(0, 0);
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)1); //TODO is it really 1?
}
// This method normalizes the Point coordinates,
// Optionally flips them horizontally
// Adjusts the height (y-coordinate) to make the virtual points not squished (puts them into a rectangle)
// Returns the Points as Point2D
public Point2D[] normalizePoints(Point[] points, boolean isBacksite) {
if(points == null) return null;
Point2D normalizedPoints[] = new Point2D.Double[points.length];
for(int i = 0; i < normalizedPoints.length; i++) {
}
//TODO is this still needed?
if(isBacksite) {
for(int i = 0; i < normalizedPoints.length; i++) {
normalizedPoints[i].setLocation(-normalizedPoints[i].getX(), normalizedPoints[i].getY());
}
}
return normalizedPoints;
}
/**
* Normalizes 3D points with the given parameters and returns a NEW array with the normalized points. To see which coordinate dimension represents what direction, view Point3D class
* @param points
* @param baseline for z coordinates. Can be different to the lowest LED
* @param minX minimal X value of LED box
* @param minY minimal Y value of LED box
* @param maxX maximal X value of LED box
* @param maxY maximal Y value of LED box
* @return new Array with normalized Points
*/
public Point3D[] normalizePoints(Point3D[] points, double baseline, double minX, double minY, double maxX, double maxY) {
Point3D normalizedPoints[] = new Point3D[points.length];
for(int i = 0; i < normalizedPoints.length; i++) {
double normalizedX = (points[i].x - minX) / (maxX - minX);
double normalizedY = (points[i].y - minY) / (maxY - minY);
double normalizedZ = ((baseline - points[i].z) - minX) / (maxX - minX);
normalizedX = normalizedX * 2.0 - 1.0;
normalizedY = normalizedY * 2.0 - 1.0;
normalizedPoints[i] = new Point3D(normalizedX, normalizedY, normalizedZ);
}
return normalizedPoints;
}
public Point3D[] normalizePoints(Point3D[] points, double baseline) {
double lowestX = Double.POSITIVE_INFINITY;
double highestX = Double.NEGATIVE_INFINITY;
for(int i = 0; i < points.length; i++) {
if(lowestX > points[i].x) {
lowestX = points[i].x;
}
if(highestX < points[i].x) {
highestX = points[i].x;
}
}
return normalizePoints(points, baseline, lowestX, highestX, lowestX, highestX);
}
public Point3D[] normalizePoints(Point3D[] points) {
double lowestZ = Double.POSITIVE_INFINITY;
for(int i = 0; i < points.length; i++) {
if(lowestZ > points[i].z) {
lowestZ = points[i].z;
}
}
return normalizePoints(points, lowestZ);
}
}

View File

@ -0,0 +1,13 @@
package com.cringe_studios.christmastreescanning;
public class Point3D {
public double x; // baseline
public double y; // coming out of the image
public double z; // The height
public Point3D(double nx, double ny, double nz) {
x = nx;
y = ny;
z = nz;
}
}

View File

@ -0,0 +1,17 @@
package com.cringe_studios.christmastreescanning;
import java.awt.Point;
public class PointInterpolator {
Point a;
Point b;
public PointInterpolator(Point na, Point nb) {
a = na;
b = nb;
}
Point getCenter() {
return new Point( (a.x + b.x) / 2, (a.y + b.y) / 2);
}
}