Added two helper Classes and partially implemented
This commit is contained in:
parent
81d25c6a2c
commit
9a9cbfd345
@ -1,18 +1,153 @@
|
|||||||
package com.cringe_studios.christmastreescanning;
|
package com.cringe_studios.christmastreescanning;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
public class ChristmasTreeScanning {
|
public class ChristmasTreeScanning {
|
||||||
Point getBrightestSpot(BufferedImage image) {
|
private Point getBrightestSpotGrayscale(BufferedImage grayScaleImage, byte gammaDelta) {
|
||||||
int[] imageColors = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, 0);
|
int[] imageColors = grayScaleImage.getRGB(0, 0, grayScaleImage.getWidth(), grayScaleImage.getHeight(), null, 0, 0);
|
||||||
|
|
||||||
for(int i = 0; i < imageColors.length; i++) {
|
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);
|
Point brightestSpot = new Point(0, 0);
|
||||||
|
|
||||||
return brightestSpot;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user