diff --git a/src/main/java/com/cringe_studios/christmastreescanning/scanning/ChristmasTreeScanning.java b/src/main/java/com/cringe_studios/christmastreescanning/scanning/ChristmasTreeScanning.java index 602500e..0490c4b 100644 --- a/src/main/java/com/cringe_studios/christmastreescanning/scanning/ChristmasTreeScanning.java +++ b/src/main/java/com/cringe_studios/christmastreescanning/scanning/ChristmasTreeScanning.java @@ -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 brightSpots = new ArrayList(); - - 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, diff --git a/src/main/java/com/cringe_studios/christmastreescanning/scanning/ImageScanner.java b/src/main/java/com/cringe_studios/christmastreescanning/scanning/ImageScanner.java new file mode 100644 index 0000000..0ab75d5 --- /dev/null +++ b/src/main/java/com/cringe_studios/christmastreescanning/scanning/ImageScanner.java @@ -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 brightSpots = new ArrayList(); + + 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); + } +} diff --git a/src/main/java/com/cringe_studios/christmastreescanning/scanning/SideScanner.java b/src/main/java/com/cringe_studios/christmastreescanning/scanning/SideScanner.java index 7c0afc2..8822dac 100644 --- a/src/main/java/com/cringe_studios/christmastreescanning/scanning/SideScanner.java +++ b/src/main/java/com/cringe_studios/christmastreescanning/scanning/SideScanner.java @@ -1,5 +1,95 @@ package com.cringe_studios.christmastreescanning.scanning; -public class SideScanner { +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 + } + }