Implemented a part of SideScanner and added ImageScanner: scans a single
image
This commit is contained in:
parent
b750ae9344
commit
b3031ad97f
@ -10,89 +10,6 @@ import java.util.List;
|
|||||||
import com.cringe_studios.christmastreescanning.Point3D;
|
import com.cringe_studios.christmastreescanning.Point3D;
|
||||||
|
|
||||||
public class ChristmasTreeScanning {
|
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,
|
// This method normalizes the Point coordinates,
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,95 @@
|
|||||||
package com.cringe_studios.christmastreescanning.scanning;
|
package com.cringe_studios.christmastreescanning.scanning;
|
||||||
|
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
public class SideScanner {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user