From 1befac154e47e8ba4116ec8b159f3d281fc2f97d Mon Sep 17 00:00:00 2001 From: Paul Schaller Date: Thu, 23 Nov 2023 18:31:41 +0100 Subject: [PATCH] Finished Implementation of Homograph (the part of the project that merges multiple images together)(Not tested yet, as nearly everything) --- .../christmastreescanning/Homograph.java | 9 +++ .../christmastreescanning/Homograph2.java | 68 +++++++++++++++++++ .../christmastreescanning/Homograph4.java | 48 +++++++++++++ .../christmastreescanning/Scanner.java | 2 +- .../TwoSidedScanner.java | 2 +- 5 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/cringe_studios/christmastreescanning/Homograph.java create mode 100644 src/main/java/com/cringe_studios/christmastreescanning/Homograph2.java create mode 100644 src/main/java/com/cringe_studios/christmastreescanning/Homograph4.java diff --git a/src/main/java/com/cringe_studios/christmastreescanning/Homograph.java b/src/main/java/com/cringe_studios/christmastreescanning/Homograph.java new file mode 100644 index 0000000..9141621 --- /dev/null +++ b/src/main/java/com/cringe_studios/christmastreescanning/Homograph.java @@ -0,0 +1,9 @@ +package com.cringe_studios.christmastreescanning; + +import java.awt.geom.Point2D; + +public interface Homograph { + void merge(); + void renormalize(); + Point3D[] getPoints(); +} diff --git a/src/main/java/com/cringe_studios/christmastreescanning/Homograph2.java b/src/main/java/com/cringe_studios/christmastreescanning/Homograph2.java new file mode 100644 index 0000000..c3212c5 --- /dev/null +++ b/src/main/java/com/cringe_studios/christmastreescanning/Homograph2.java @@ -0,0 +1,68 @@ +package com.cringe_studios.christmastreescanning; + +import java.awt.geom.Point2D; +import java.util.Arrays; + +import com.cringe_studios.christmastreescanning.scanning.PointInterpolator; + +public class Homograph2 implements Homograph{ + // The 3D Homograph simply tries to find an intersection of two lines. One line comes from the "front" side, and the other line comes from the "right" side. These two sides are 90° apart. + + SingleHomograph homographs[]; + + //Simple Implementation; does not account for: + // - scanning error + // - incorrect rotation of tree + // - change of camera type midway through + // - rotation of camera (accidently hitting laptop while scanning) + // - different position of camera (laptop was moved while scanning) + private class SingleHomograph{ + Point2D frontSidePoint; + Point2D rightSidePoint; + + Point3D mergedPoint; + + public SingleHomograph(Point2D newFrontSidePoint, Point2D newRightSidePoint) { + this.frontSidePoint = newFrontSidePoint; + this.rightSidePoint = newRightSidePoint; + } + + public void merge() { + double newz = new PointInterpolator(frontSidePoint, rightSidePoint).getCenter().getY(); + double newx = frontSidePoint.getX(); //baseline + double newy = rightSidePoint.getX(); //coming out of the image + mergedPoint = new Point3D(newx, newy, newz); + } + + public Point3D getPoint() { + return mergedPoint; + } + } + + public Homograph2(Point2D[] frontSidePoints, Point2D[] rightSidePoints) { + homographs = new SingleHomograph[frontSidePoints.length]; + for(int i = 0; i < frontSidePoints.length; i++) { + homographs[i] = new SingleHomograph(frontSidePoints[i], frontSidePoints[i]); + } + } + + @Override + public void merge() { + // The implementation does not have to be perfect, as part of the requirement is, that after the scanning, the LEDs Position will be tested. + + Arrays.stream(homographs).forEach(i -> i.merge()); + } + + @Override + public void renormalize() { + //After the points are merged, depending on the implementation of the merging algorithm, the points might need to be renormalized + //This specific Algorithm does not need to be remerged + //TODO double check that fact with a test + + } + + @Override + public Point3D[] getPoints() { + return Arrays.stream(homographs).map(i -> i.getPoint()).toArray(Point3D[]::new); + } +} diff --git a/src/main/java/com/cringe_studios/christmastreescanning/Homograph4.java b/src/main/java/com/cringe_studios/christmastreescanning/Homograph4.java new file mode 100644 index 0000000..f4f5259 --- /dev/null +++ b/src/main/java/com/cringe_studios/christmastreescanning/Homograph4.java @@ -0,0 +1,48 @@ +package com.cringe_studios.christmastreescanning; + +import java.awt.geom.Point2D; + +import com.cringe_studios.christmastreescanning.scanning.PointInterpolator; + +public class Homograph4 implements Homograph{ + // Homograph 4 simplifies the code by first merging back and front side, as well as right and left side together. This step isn't perfect though, because the scanned images are not perfect. + private Homograph2 internalHomograph; + + public Homograph4(Point2D[] frontSidePoints, Point2D[] rightSidePoints, Point2D[] behindSidePoints, Point2D[] leftSidePoints) { + Point2D[] mergedFrontBack = new Point2D[frontSidePoints.length]; + Point2D[] mergedRightLeft = new Point2D[frontSidePoints.length]; + + Point2D[] flippedBehindSide = new Point2D[frontSidePoints.length]; + Point2D[] flippedLeftSide = new Point2D[frontSidePoints.length]; + + for(int i = 0; i < frontSidePoints.length; i++) { + // the x coordinate goes from -1 to 1 after normalization + flippedBehindSide[i] = new Point2D.Double(behindSidePoints[i].getX() * -1.0, behindSidePoints[i].getY()); + flippedLeftSide[i] = new Point2D.Double(leftSidePoints[i].getX() * -1.0, leftSidePoints[i].getY()); + } + + + for(int i = 0; i < frontSidePoints.length; i++) { + Point2D interpolatedFrontBehind = new PointInterpolator(frontSidePoints[i], flippedBehindSide[i]).getCenter(); + Point2D interpolatedRightLeft = new PointInterpolator(rightSidePoints[i], leftSidePoints[i]).getCenter(); + + mergedFrontBack[i] = interpolatedFrontBehind; + mergedRightLeft[i] = interpolatedRightLeft; + } + } + + @Override + public void merge() { + internalHomograph.merge(); + } + + @Override + public void renormalize() { + internalHomograph.renormalize(); + } + + @Override + public Point3D[] getPoints() { + return internalHomograph.getPoints(); + } +} diff --git a/src/main/java/com/cringe_studios/christmastreescanning/Scanner.java b/src/main/java/com/cringe_studios/christmastreescanning/Scanner.java index 3de917f..3528f87 100644 --- a/src/main/java/com/cringe_studios/christmastreescanning/Scanner.java +++ b/src/main/java/com/cringe_studios/christmastreescanning/Scanner.java @@ -32,7 +32,7 @@ public abstract class Scanner { // public Scanner() {} -public abstract Point3D[] scan(); +public abstract Homograph scan(); // public Point3D[] scan() { // if(distinctColorChannels == null || sideCount == null); //TODO error diff --git a/src/main/java/com/cringe_studios/christmastreescanning/TwoSidedScanner.java b/src/main/java/com/cringe_studios/christmastreescanning/TwoSidedScanner.java index e81d59c..9fb29af 100644 --- a/src/main/java/com/cringe_studios/christmastreescanning/TwoSidedScanner.java +++ b/src/main/java/com/cringe_studios/christmastreescanning/TwoSidedScanner.java @@ -19,7 +19,7 @@ public class TwoSidedScanner extends SingleColorScanner { } @Override - public Point3D[] scan() { + public Homograph scan() { // TODO Auto-generated method stub frontSideScanner.scan(); frontSideScanner.normalizePoints();