From 3a3df948d52f75899124ad26e3c52caf6beb3a2f Mon Sep 17 00:00:00 2001 From: Nicolas Feybesse Date: Tue, 15 May 2018 18:28:33 +0200 Subject: [PATCH] Fix lines identification + refactoring --- .../cv/application/HoughTrajectStep.java | 23 ++ .../cv/application/RadonTransform.java | 94 +++--- .../cv/application/RadonTransformDemo.java | 103 +++--- .../cv/application/RadonTransformDemo2.java | 297 +++++++----------- .../cv/application/RadonTransformDemo3.java | 98 +----- .../cv/application/TrajectStep.java | 2 +- 6 files changed, 245 insertions(+), 372 deletions(-) create mode 100644 gs-cv/src/main/java/org/genericsystem/cv/application/HoughTrajectStep.java diff --git a/gs-cv/src/main/java/org/genericsystem/cv/application/HoughTrajectStep.java b/gs-cv/src/main/java/org/genericsystem/cv/application/HoughTrajectStep.java new file mode 100644 index 000000000..e73d5cc8c --- /dev/null +++ b/gs-cv/src/main/java/org/genericsystem/cv/application/HoughTrajectStep.java @@ -0,0 +1,23 @@ +package org.genericsystem.cv.application; + +public class HoughTrajectStep implements Comparable { + final int y; + final double derivative; + final double magnitude; + + public HoughTrajectStep(int y, double derivative, double magnitude) { + this.y = y; + this.derivative = derivative; + this.magnitude = magnitude; + } + + @Override + public int compareTo(HoughTrajectStep step) { + return Double.compare(step.magnitude, magnitude); + } + + public double getTheta() { + return Math.atan(derivative) / Math.PI * 180 + 45; + } + +} \ No newline at end of file diff --git a/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransform.java b/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransform.java index b9b20fcdc..250caecf2 100644 --- a/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransform.java +++ b/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransform.java @@ -1,5 +1,16 @@ package org.genericsystem.cv.application; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + import org.apache.commons.math3.analysis.interpolation.LinearInterpolator; import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction; import org.genericsystem.cv.Img; @@ -19,17 +30,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - public class RadonTransform { static { @@ -259,23 +259,38 @@ public static TrajectStep[] bestTrajectRadon(Mat projectionMap, double anglePena return thetas; } - public static TrajectStep[] bestTrajectFHT(Mat projectionMap, double anglePenality) { - List penality = IntStream.range(0, projectionMap.cols()).mapToObj(theta -> anglePenality * Math.abs(Math.atan((double) (theta - 45) / 45) - Math.atan((double) (theta + 1 - 45) / (45))) * 180 / Math.PI).collect(Collectors.toList()); - double[][] score = new double[projectionMap.rows()][projectionMap.cols()]; - int[][] thetaPrev = new int[projectionMap.rows()][projectionMap.cols()]; - for (int theta = 0; theta < projectionMap.cols(); theta++) - score[0][theta] = projectionMap.get(0, theta)[0]; - for (int k = 1; k < projectionMap.rows(); k++) { - for (int theta = 0; theta < projectionMap.cols(); theta++) { - double magnitude = projectionMap.get(k, theta)[0]; + static Mat adaptivHough(Mat houghTransform, int blurSize) { + Mat adaptivHough = new Mat(); + Mat blur = new Mat(); + Imgproc.blur(houghTransform, blur, new Size(1, blurSize), new Point(-1, -1), Core.BORDER_ISOLATED); + Core.absdiff(houghTransform, blur, adaptivHough); + blur.release(); + // adaptivHough.row(0).setTo(new Scalar(0)); + // adaptivHough.row(houghTransform.rows() - 1).setTo(new Scalar(0)); + // Core.pow(adaptivHough, 2, adaptivHough); + return adaptivHough; + } + + public static List bestTrajectFHT(Mat houghTransform, int blurSize, double anglePenality) { + int stripWidth = (houghTransform.cols() + 1) / 2; + Mat adaptivHough = adaptivHough(houghTransform, blurSize); + List penality = IntStream.range(0, adaptivHough.cols()) + .mapToObj(theta -> anglePenality * Math.abs(Math.atan((double) (theta - stripWidth + 1) / (stripWidth - 1)) - Math.atan((double) (theta - stripWidth + 2) / (stripWidth - 1))) * 180 / Math.PI).collect(Collectors.toList()); + double[][] score = new double[adaptivHough.rows()][adaptivHough.cols()]; + int[][] thetaPrev = new int[adaptivHough.rows()][adaptivHough.cols()]; + for (int theta = 0; theta < adaptivHough.cols(); theta++) + score[0][theta] = adaptivHough.get(0, theta)[0]; + for (int k = 1; k < adaptivHough.rows(); k++) { + for (int theta = 0; theta < adaptivHough.cols(); theta++) { + double magnitude = adaptivHough.get(k, theta)[0]; double scoreFromPrevTheta = theta != 0 ? score[k - 1][theta - 1] : Double.NEGATIVE_INFINITY; double scoreFromSameTheta = score[k - 1][theta]; - double scoreFromNextTheta = theta < projectionMap.cols() - 1 ? score[k - 1][theta + 1] : Double.NEGATIVE_INFINITY; + double scoreFromNextTheta = theta < adaptivHough.cols() - 1 ? score[k - 1][theta + 1] : Double.NEGATIVE_INFINITY; double bestScore4Pos = -1; double prevPenality = theta == 0 ? Double.NEGATIVE_INFINITY : penality.get(theta - 1); - double nextPenality = theta <= projectionMap.cols() ? penality.get(theta) : Double.NEGATIVE_INFINITY; + double nextPenality = theta <= adaptivHough.cols() ? penality.get(theta) : Double.NEGATIVE_INFINITY; if (scoreFromSameTheta >= (scoreFromPrevTheta + prevPenality) && scoreFromSameTheta >= (scoreFromNextTheta + nextPenality)) { bestScore4Pos = scoreFromSameTheta; @@ -291,23 +306,26 @@ public static TrajectStep[] bestTrajectFHT(Mat projectionMap, double anglePenali } } + adaptivHough.release(); + double maxScore = Double.NEGATIVE_INFINITY; int prevTheta = -1; - for (int theta = 0; theta < projectionMap.cols(); theta++) { - double lastScore = score[projectionMap.rows() - 1][theta]; + for (int theta = 0; theta < houghTransform.cols(); theta++) { + double lastScore = score[houghTransform.rows() - 1][theta]; if (lastScore > maxScore) { maxScore = lastScore; prevTheta = theta; } } + assert prevTheta != -1; - TrajectStep[] thetas = new TrajectStep[projectionMap.rows()]; - for (int k = projectionMap.rows() - 1; k >= 0; k--) { - thetas[k] = new TrajectStep(k, prevTheta, projectionMap.get(k, prevTheta)[0]); - prevTheta = thetaPrev[k][prevTheta]; + HoughTrajectStep[] result = new HoughTrajectStep[houghTransform.rows()]; + for (int y = houghTransform.rows() - 1; y >= 0; y--) { + double derivative = ((double) prevTheta - (stripWidth - 1)) / (stripWidth - 1); + result[y] = new HoughTrajectStep(y, derivative, houghTransform.get(y, prevTheta)[0]); + prevTheta = thetaPrev[y][prevTheta]; } - - return thetas; + return Arrays.asList(result); } public static List extractStrips(Mat src, int stripNumber, double stripWidth, double step) { @@ -406,20 +424,20 @@ public static List toVerticalOrientedPoints(Function toHorizontalOrientedPoints(TrajectStep[] trajectSteps, double x) { + public static List toHorizontalOrientedPoints(List trajectSteps, double x) { List orientedPoints = new ArrayList<>(); - Arrays.stream(trajectSteps).filter(ts -> ts.magnitude >= 0.1).sorted().limit(100).forEach(trajectStep -> { - double angle = ((double) trajectStep.theta - 45) / 180 * Math.PI; - orientedPoints.add(new OrientedPoint(new Point(x, trajectStep.k), angle, trajectStep.magnitude)); + trajectSteps.stream().filter(ts -> ts.magnitude >= 0.1).sorted().limit(30).forEach(trajectStep -> { + double angle = (trajectStep.getTheta() - 45) / 180 * Math.PI; + orientedPoints.add(new OrientedPoint(new Point(x, trajectStep.y), angle, trajectStep.magnitude)); }); return orientedPoints; } - public static List toVerticalOrientedPoints(TrajectStep[] trajectSteps, double y) { + public static List toVerticalOrientedPoints(List trajectSteps, double y) { List orientedPoints = new ArrayList<>(); - Arrays.stream(trajectSteps).filter(ts -> ts.magnitude >= 0.1).sorted().limit(100).forEach(trajectStep -> { - double angle = -((double) trajectStep.theta - 45) / 180 * Math.PI; - orientedPoints.add(new OrientedPoint(new Point(trajectStep.k, y), angle, trajectStep.magnitude)); + trajectSteps.stream().filter(ts -> ts.magnitude >= 0.1).sorted().limit(30).forEach(trajectStep -> { + double angle = -(trajectStep.getTheta() - 45) / 180 * Math.PI; + orientedPoints.add(new OrientedPoint(new Point(trajectStep.y, y), angle, trajectStep.magnitude)); }); return orientedPoints; } diff --git a/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo.java b/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo.java index fe76961c0..91e324934 100644 --- a/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo.java +++ b/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo.java @@ -1,5 +1,14 @@ package org.genericsystem.cv.application; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction; import org.genericsystem.cv.AbstractApp; import org.genericsystem.cv.Img; @@ -11,15 +20,6 @@ import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.stream.Collectors; - import javafx.application.Platform; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -149,29 +149,22 @@ private Image[] doWork() { List vTrajs = vProjectionMaps.stream().map(projectionMap -> RadonTransform.bestTrajectRadon(projectionMap, -1000)).collect(Collectors.toList()); List hTrajs = hProjectionMaps.stream().map(projectionMap -> RadonTransform.bestTrajectRadon(projectionMap, -1000)).collect(Collectors.toList()); - List vHoughTrajs = vHoughs.stream().map(projectionMap -> RadonTransform.bestTrajectFHT(projectionMap, -1000)).collect(Collectors.toList()); - List hHoughTrajs = hHoughs.stream().map(projectionMap -> RadonTransform.bestTrajectFHT(projectionMap, -1000)).collect(Collectors.toList()); + List> vHoughTrajs = vHoughs.stream().map(projectionMap -> RadonTransform.bestTrajectFHT(projectionMap, 11, -50)).collect(Collectors.toList()); + List> hHoughTrajs = hHoughs.stream().map(projectionMap -> RadonTransform.bestTrajectFHT(projectionMap, 11, -50)).collect(Collectors.toList()); ref = trace("Compute trajects", ref); - for (TrajectStep[] houghVtraj : vHoughTrajs) - for (int y = 0; y < houghVtraj.length; y++) - houghVtraj[y].theta = (int) Math.round(Math.atan((double) (houghVtraj[y].theta - 45) / 45) / Math.PI * 180 + 45); - - for (TrajectStep[] houghHtraj : hHoughTrajs) - for (int y = 0; y < houghHtraj.length; y++) - houghHtraj[y].theta = (int) Math.round(Math.atan((double) (houghHtraj[y].theta - 45) / 45) / Math.PI * 180 + 45); ref = trace("Transform trajects", ref); List> approxVFunctions = vTrajs.stream().map(traj -> RadonTransform.approxTraject(traj)).collect(Collectors.toList()); List> approxHFunctions = hTrajs.stream().map(traj -> RadonTransform.approxTraject(traj)).collect(Collectors.toList()); - List> approxVFHTFunctions = vHoughTrajs.stream().map(traj -> RadonTransform.approxTraject(traj)).collect(Collectors.toList()); - List> approxHFHTFunctions = hHoughTrajs.stream().map(traj -> RadonTransform.approxTraject(traj)).collect(Collectors.toList()); + // List> approxVFHTFunctions = vHoughTrajs.stream().map(traj -> RadonTransform.approxTraject(traj)).collect(Collectors.toList()); + // List> approxHFHTFunctions = hHoughTrajs.stream().map(traj -> RadonTransform.approxTraject(traj)).collect(Collectors.toList()); ref = trace("Compute approxs", ref); List vRadonSplinesFunctions = RadonTransform.toPolynomialSplineFunction(approxVFunctions, binarized.getSrc().size(), 20, minAngle, vStrips.size(), 0.5f); List hRadonSplinesFunctions = RadonTransform.toPolynomialSplineFunction(approxHFunctions, transposedBinarized.getSrc().size(), 20, minAngle, hStrips.size(), 0.5f); - List vFHTSplinesFunctions = RadonTransform.toPolynomialSplineFunction(approxVFHTFunctions, binarized.getSrc().size(), 20, minAngle, vStrips.size(), 0.5f); - List hFHTSplinesFunctions = RadonTransform.toPolynomialSplineFunction(approxHFHTFunctions, transposedBinarized.getSrc().size(), 20, minAngle, hStrips.size(), 0.5f); + // List vFHTSplinesFunctions = RadonTransform.toPolynomialSplineFunction(approxVFHTFunctions, binarized.getSrc().size(), 20, minAngle, vStrips.size(), 0.5f); + // List hFHTSplinesFunctions = RadonTransform.toPolynomialSplineFunction(approxHFHTFunctions, transposedBinarized.getSrc().size(), 20, minAngle, hStrips.size(), 0.5f); Mat image = superFrame.getFrame().getSrc().clone(); RadonTransform.displayHSplines(vRadonSplinesFunctions, image); @@ -192,8 +185,8 @@ private Image[] doWork() { images[10] = new Img(image, false).toJfxImage(); Mat image2 = superFrame.getFrame().getSrc().clone(); - RadonTransform.displayHSplines(vFHTSplinesFunctions, image2); - RadonTransform.displayVSplines(hFHTSplinesFunctions, image2); + // RadonTransform.displayHSplines(vFHTSplinesFunctions, image2); + // RadonTransform.displayVSplines(hFHTSplinesFunctions, image2); images[11] = new Img(image2, false).toJfxImage(); ref = trace("Compute cubic spline lines", ref); @@ -212,12 +205,12 @@ private Image[] doWork() { vStrip = 0; List fhtHorizontals = new ArrayList<>(); - for (Function f : approxVFHTFunctions) - fhtHorizontals.addAll(RadonTransform.toHorizontalOrientedPoints(f, (vStrip++ + 1) * hStep, binarized.height(), (int) hStep)); + // for (Function f : approxVFHTFunctions) + // fhtHorizontals.addAll(RadonTransform.toHorizontalOrientedPoints(f, (vStrip++ + 1) * hStep, binarized.height(), (int) hStep)); hStrip = 0; List fhtVerticals = new ArrayList<>(); - for (Function f : approxHFHTFunctions) - fhtVerticals.addAll(RadonTransform.toVerticalOrientedPoints(f, (hStrip++ + 1) * vStep, binarized.width(), (int) vStep)); + // for (Function f : approxHFHTFunctions) + // fhtVerticals.addAll(RadonTransform.toVerticalOrientedPoints(f, (hStrip++ + 1) * vStep, binarized.width(), (int) vStep)); GeneralInterpolator interpolatorFHT = new GeneralInterpolator(fhtHorizontals, fhtVerticals, 3, 10); @@ -253,33 +246,33 @@ private Image[] doWork() { images[1] = frameDisplay.toJfxImage(); - Img frameDisplayFHT = new Img(superFrame.getFrame().getSrc().clone(), false); - vStrip = 0; - for (Function f : approxVFHTFunctions) { - for (int k = (int) hStep; k + hStep <= binarized.height(); k += hStep) { - double angle = (f.apply((double) k) - minAngle) / 180 * Math.PI; - Imgproc.line(frameDisplayFHT.getSrc(), new Point((vStrip + 1) * stripWidth / 2 - Math.cos(angle) * stripWidth / 6, k - Math.sin(angle) * stripWidth / 6), - new Point((vStrip + 1) * stripWidth / 2 + Math.cos(angle) * stripWidth / 6, k + Math.sin(angle) * stripWidth / 6), new Scalar(0, 255, 0), 2); - angle = interpolatorFHT.interpolateVerticals((vStrip + 1) * stripWidth / 2, k); - Imgproc.line(frameDisplayFHT.getSrc(), new Point((vStrip + 1) * stripWidth / 2 - Math.cos(angle) * stripWidth / 6, k - Math.sin(angle) * stripWidth / 6), - new Point((vStrip + 1) * stripWidth / 2 + Math.cos(angle) * stripWidth / 6, k + Math.sin(angle) * stripWidth / 6), new Scalar(255, 0, 0), 2); - } - vStrip++; - } - hStrip = 0; - for (Function f : approxHFHTFunctions) { - for (int k = (int) vStep; k + vStep <= binarized.width(); k += vStep) { - double angle = (90 + minAngle - (f.apply((double) k))) / 180 * Math.PI; - Imgproc.line(frameDisplayFHT.getSrc(), new Point(k - Math.cos(angle) * stripHeight / 6, (hStrip + 1) * stripHeight / 2 - Math.sin(angle) * stripHeight / 6), - new Point(k + Math.cos(angle) * stripHeight / 6, (hStrip + 1) * stripHeight / 2 + Math.sin(angle) * stripHeight / 6), new Scalar(0, 0, 255), 2); - angle = interpolatorFHT.interpolateHorizontals(k, (hStrip + 1) * stripHeight / 2); - Imgproc.line(frameDisplayFHT.getSrc(), new Point(k - Math.cos(angle) * stripHeight / 6, (hStrip + 1) * stripHeight / 2 - Math.sin(angle) * stripHeight / 6), - new Point(k + Math.cos(angle) * stripHeight / 6, (hStrip + 1) * stripHeight / 2 + Math.sin(angle) * stripHeight / 6), new Scalar(255, 0, 0), 2); - - } - hStrip++; - } - images[2] = frameDisplayFHT.toJfxImage(); + // Img frameDisplayFHT = new Img(superFrame.getFrame().getSrc().clone(), false); + // vStrip = 0; + // for (Function f : approxVFHTFunctions) { + // for (int k = (int) hStep; k + hStep <= binarized.height(); k += hStep) { + // double angle = (f.apply((double) k) - minAngle) / 180 * Math.PI; + // Imgproc.line(frameDisplayFHT.getSrc(), new Point((vStrip + 1) * stripWidth / 2 - Math.cos(angle) * stripWidth / 6, k - Math.sin(angle) * stripWidth / 6), + // new Point((vStrip + 1) * stripWidth / 2 + Math.cos(angle) * stripWidth / 6, k + Math.sin(angle) * stripWidth / 6), new Scalar(0, 255, 0), 2); + // angle = interpolatorFHT.interpolateVerticals((vStrip + 1) * stripWidth / 2, k); + // Imgproc.line(frameDisplayFHT.getSrc(), new Point((vStrip + 1) * stripWidth / 2 - Math.cos(angle) * stripWidth / 6, k - Math.sin(angle) * stripWidth / 6), + // new Point((vStrip + 1) * stripWidth / 2 + Math.cos(angle) * stripWidth / 6, k + Math.sin(angle) * stripWidth / 6), new Scalar(255, 0, 0), 2); + // } + // vStrip++; + // } + // hStrip = 0; + // for (Function f : approxHFHTFunctions) { + // for (int k = (int) vStep; k + vStep <= binarized.width(); k += vStep) { + // double angle = (90 + minAngle - (f.apply((double) k))) / 180 * Math.PI; + // Imgproc.line(frameDisplayFHT.getSrc(), new Point(k - Math.cos(angle) * stripHeight / 6, (hStrip + 1) * stripHeight / 2 - Math.sin(angle) * stripHeight / 6), + // new Point(k + Math.cos(angle) * stripHeight / 6, (hStrip + 1) * stripHeight / 2 + Math.sin(angle) * stripHeight / 6), new Scalar(0, 0, 255), 2); + // angle = interpolatorFHT.interpolateHorizontals(k, (hStrip + 1) * stripHeight / 2); + // Imgproc.line(frameDisplayFHT.getSrc(), new Point(k - Math.cos(angle) * stripHeight / 6, (hStrip + 1) * stripHeight / 2 - Math.sin(angle) * stripHeight / 6), + // new Point(k + Math.cos(angle) * stripHeight / 6, (hStrip + 1) * stripHeight / 2 + Math.sin(angle) * stripHeight / 6), new Scalar(255, 0, 0), 2); + // + // } + // hStrip++; + // } + // images[2] = frameDisplayFHT.toJfxImage(); ref = trace("Display lines", ref); diff --git a/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo2.java b/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo2.java index 528cfc553..5c6bea979 100644 --- a/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo2.java +++ b/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo2.java @@ -2,8 +2,11 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -105,163 +108,133 @@ private Image[] doWork() { Mat vStripDisplay = Mat.zeros(binarized.size(), binarized.type()); Mat roi = new Mat(vStripDisplay, new Range(0, binarized.height()), new Range(binarized.width() / 2 - stripWidth / 2, binarized.width() / 2 + stripWidth / 2)); vStrip.copyTo(roi); - Mat roi2 = new Mat(vStripDisplay, new Range(0, binarized.height()), new Range(binarized.width() / 2 - stripWidth / 2 + w, binarized.width() / 2 + stripWidth / 2 + w)); - vStrip2.copyTo(roi2); + // Mat roi2 = new Mat(vStripDisplay, new Range(0, binarized.height()), new Range(binarized.width() / 2 - stripWidth / 2 + w, binarized.width() / 2 + stripWidth / 2 + w)); + // vStrip2.copyTo(roi2); images[1] = new Img(vStripDisplay, false).toJfxImage(); ref = trace("Extract strip", ref); Mat houghTransform = RadonTransform.fastHoughTransform(vStrip); - Mat houghTransform2 = RadonTransform.fastHoughTransform(vStrip2); + // Mat houghTransform2 = RadonTransform.fastHoughTransform(vStrip2); + System.out.println(houghTransform); // houghTransform.row(0).setTo(new Scalar(0)); // houghTransform.row(houghTransform.rows() - 1).setTo(new Scalar(0)); Core.normalize(houghTransform, houghTransform, 0, 255, Core.NORM_MINMAX); // Core.normalize(houghTransform2, houghTransform2, 0, 255, Core.NORM_MINMAX); - // Mat shift = Mat.zeros(houghTransform2.size(), houghTransform2.type()); - // for (int col = 0; col < shift.width(); col++) { - // int rowShift = (int) Math.round((double) w * ((col - (stripWidth - 1)) / (stripWidth - 1))); - // for (int row = 0; row < shift.height(); row++) { - // if (row + rowShift >= 0 && row + rowShift < shift.height()) - // shift.put(row + rowShift, col, houghTransform2.get(row, col)[0]); - // } - // } - // - // Core.absdiff(shift, houghTransform, shift); - // - // Mat concat = new Mat(houghTransform.size(), CvType.CV_64FC1); - // Core.hconcat(Arrays.asList(houghTransform, shift), concat); - - images[3] = new Img(houghTransform, false).toJfxImage(); - ref = trace("FHT", ref); - Mat gradient = new Mat(); Mat blur = new Mat(); Imgproc.blur(houghTransform, blur, new Size(1, 11), new Point(-1, -1), Core.BORDER_ISOLATED); - Core.absdiff(houghTransform, blur, gradient); images[2] = new Img(blur, false).toJfxImage(); - // gradient.row(0).setTo(new Scalar(0)); - // gradient.row(houghTransform.rows() - 1).setTo(new Scalar(0)); - Core.pow(gradient, 2, gradient); - Core.normalize(gradient, gradient, 0, 255, Core.NORM_MINMAX); - images[4] = new Img(gradient, false).toJfxImage(); - ref = trace("FHT Gradient", ref); - - TrajectStep[] houghVtraj = RadonTransform.bestTrajectFHT(gradient, -50); - List magnitudes = new ArrayList<>(); - for (int row = 0; row < houghVtraj.length; row++) { - double magnitude = houghTransform.get(row, houghVtraj[row].theta)[0]; - magnitudes.add(magnitude); - } + blur.release(); - for (int y = 0; y < houghVtraj.length; y++) - houghVtraj[y].theta = (int) Math.round(Math.atan((double) (houghVtraj[y].theta - (stripWidth - 1)) / (stripWidth - 1)) / Math.PI * 180 + 45); + images[3] = new Img(houghTransform, false).toJfxImage(); + ref = trace("FHT", ref); - for (int y = 0; y < houghVtraj.length; y++) { - if (houghVtraj[y].magnitude <= 1) - for (int end = y + 1; end < houghVtraj.length; end++) { - if (houghVtraj[end].magnitude > 1) { - for (int current = y; current < end; current++) - houghVtraj[current].theta = houghVtraj[y == 0 ? 0 : y - 1].theta + (houghVtraj[end].theta - houghVtraj[y == 0 ? 0 : y - 1].theta) * (current - y) / (end - y + 1); - y = end; - break; - } - } - } + Mat adaptive = RadonTransform.adaptivHough(houghTransform, 11); + images[4] = new Img(adaptive, false).toJfxImage(); + adaptive.release(); + ref = trace("Adaptive FHT", ref); + + List magnitudes = RadonTransform.bestTrajectFHT(houghTransform, 11, -50); + // for (int y = 0; y < magnitudes.size(); y++) { + // if (magnitudes.get(y).magnitude <= 1) + // for (int end = y + 1; end < magnitudes.size(); end++) { + // if (magnitudes.get(end).magnitude > 1) { + // for (int current = y; current < end; current++) + // magnitudes.get(current).theta = magnitudes.get(y == 0 ? 0 : y - 1).theta + (magnitudes.get(end).theta - magnitudes.get(y == 0 ? 0 : y - 1).theta) * (current - y) / (end - y + 1); + // y = end; + // break; + // } + // } + // } - Mat vHoughColor = Mat.zeros(houghTransform.height(), 91, CvType.CV_8UC3); - for (int y = 0; y < vHoughColor.height(); y++) { - vHoughColor.put(y, houghVtraj[y].theta, 0, 0, 255); - if (houghVtraj[y].magnitude >= 1) - vHoughColor.put(y, houghVtraj[y].theta, 255, 0, 0); - } - images[5] = new Img(vHoughColor, false).toJfxImage(); + Mat trajectDisplay = Mat.zeros(houghTransform.height(), 90, CvType.CV_8UC3); + for (HoughTrajectStep step : magnitudes) + if (step.magnitude >= 1) + trajectDisplay.put(step.y, (int) Math.round(step.getTheta()), 255, 0, 0); + else + trajectDisplay.put(step.y, (int) Math.round(step.getTheta()), 0, 0, 255); + images[5] = new Img(trajectDisplay, false).toJfxImage(); ref = trace("FHT traject", ref); - Mat comb = Mat.zeros(magnitudes.size(), 255, CvType.CV_8UC1); - for (TrajectStep trajectStep : houghVtraj) - Imgproc.line(comb, new Point(0, trajectStep.k), new Point(trajectStep.magnitude, trajectStep.k), new Scalar(255)); - // for (int row = 0; row < comb.rows(); row++) - // Imgproc.line(comb, new Point(0, row), new Point(magnitudes.get(row), row), new Scalar(255)); - - ref = trace("Display comb", ref); - images[6] = new Img(comb, false).toJfxImage(); - - List magnitudesGradient = new ArrayList<>(); - Mat gradientComb = Mat.zeros(houghVtraj.length, 255, CvType.CV_8UC3); - for (int row = 0; row < magnitudes.size(); row++) { - double dmag1 = magnitudes.get(row) - (row > 0 ? magnitudes.get(row - 1) : magnitudes.get(row)); - double dmag2 = ((row < magnitudes.size() - 1) ? magnitudes.get(row + 1) : magnitudes.get(row)) - magnitudes.get(row); - - if (dmag1 >= 0 && dmag2 < 0) { - magnitudesGradient.add(dmag1); - } else if (dmag1 < 0 && dmag2 >= 0) { - magnitudesGradient.add(0d); - } else if (dmag1 >= 0 && dmag2 >= 0) { - if (dmag1 >= dmag2) - magnitudesGradient.add(dmag1); - else - magnitudesGradient.add(0d); - } else if (dmag1 < 0 && dmag2 < 0) { - if (dmag1 < dmag2) - magnitudesGradient.add(dmag1); - else - magnitudesGradient.add(0d); - } else { - magnitudesGradient.add(0d); - } - - // Scalar color = dmag > 0 ? new Scalar(0, 255, 0) : new Scalar(0, 0, 255); - // Imgproc.line(gradientComb, new Point(0, row), new Point(Math.abs(dmag), row), color); - } - - List selectedMagnitudesGradient = new ArrayList<>(); - for (int row = 0; row < magnitudesGradient.size();) { - if (magnitudesGradient.get(row) >= 0) { - double maxGradient = magnitudesGradient.get(row); - int maxPositiveGradientIndex = row; - for (int positiveGradientIndex = row; positiveGradientIndex < magnitudesGradient.size() && magnitudesGradient.get(positiveGradientIndex) >= 0; positiveGradientIndex++) { - double dmag = magnitudesGradient.get(positiveGradientIndex); - if (dmag >= maxGradient) { - maxGradient = dmag; - maxPositiveGradientIndex = positiveGradientIndex; - } - } - for (int positiveGradientIndex = row; positiveGradientIndex < magnitudesGradient.size() && magnitudesGradient.get(positiveGradientIndex) >= 0; positiveGradientIndex++, row++) { - selectedMagnitudesGradient.add(maxPositiveGradientIndex == positiveGradientIndex ? maxGradient : 0); - } - } else { - double minGradient = magnitudesGradient.get(row); - int minPositiveGradientIndex = row; - for (int negativeGradientIndex = row; negativeGradientIndex < magnitudesGradient.size() && magnitudesGradient.get(negativeGradientIndex) <= 0; negativeGradientIndex++) { - double dmag = magnitudesGradient.get(negativeGradientIndex); - if (dmag < minGradient) { - minGradient = dmag; - minPositiveGradientIndex = negativeGradientIndex; + Mat magnitudesDisplay = Mat.zeros(magnitudes.size(), 255, CvType.CV_8UC1); + for (HoughTrajectStep step : magnitudes) + Imgproc.line(magnitudesDisplay, new Point(0, step.y), new Point(step.magnitude, step.y), new Scalar(255)); + images[6] = new Img(magnitudesDisplay, false).toJfxImage(); + ref = trace("Display magnitudes", ref); + + List sortedMagnitudes = new ArrayList<>(magnitudes); + Collections.sort(sortedMagnitudes); + + double alpha = 0.1; + double t = 0.5; + Set alreadyComputed = new HashSet<>(); + double max = magnitudes.stream().mapToDouble(ts -> ts.magnitude).max().getAsDouble(); + System.out.println("Max : " + max); + + List result = new ArrayList<>(); + for (HoughTrajectStep trajectStep : magnitudes.stream().sorted().collect(Collectors.toList())) { + if (trajectStep.magnitude < alpha * max) + break; + if (!alreadyComputed.contains(trajectStep)) { + double tAlpha = t * trajectStep.magnitude; + assert trajectStep.y < magnitudes.size(); + int y1 = trajectStep.y; + for (; y1 >= 0; y1--) + if (magnitudes.get(y1).magnitude < tAlpha) + break; + y1++; + assert y1 >= 0; + int y2 = trajectStep.y; + for (; y2 < magnitudes.size(); y2++) + if (magnitudes.get(y2).magnitude < tAlpha) + break; + y2--; + assert y2 < magnitudes.size(); + int[] r = new int[] { y1, y2 }; + + boolean alreadyVisited = false; + for (int k = y1; k <= y2; k++) { + if (alreadyComputed.contains(magnitudes.get(k))) { + alreadyVisited = true; + break; } } - for (int negativeGradientIndex = row; negativeGradientIndex < magnitudesGradient.size() && magnitudesGradient.get(negativeGradientIndex) <= 0; negativeGradientIndex++, row++) { - selectedMagnitudesGradient.add(minPositiveGradientIndex == negativeGradientIndex ? minGradient : 0); - } + if (!alreadyVisited) + result.add(r); + alreadyComputed.add(magnitudes.get(y1)); + alreadyComputed.add(magnitudes.get(y2)); } } - for (int row = 0; row < selectedMagnitudesGradient.size(); row++) { - double dmag = selectedMagnitudesGradient.get(row); - Scalar color = dmag > 0 ? new Scalar(0, 255, 0) : new Scalar(0, 0, 255); - Imgproc.line(gradientComb, new Point(0, row), new Point(Math.abs(dmag), row), color); + Mat rangeDisplay = magnitudesDisplay.clone(); + for (int[] y1y2 : result) { + double minMagnitude = Double.MAX_VALUE; + for (int k = y1y2[0]; k <= y1y2[1]; k++) + if (minMagnitude > magnitudes.get(k).magnitude) + minMagnitude = magnitudes.get(k).magnitude; + // System.out.println("minMagnitude : " + minMagnitude + " Range : " + y1y2[0] + " " + y1y2[1]); + Imgproc.line(rangeDisplay, new Point(minMagnitude, y1y2[0]), new Point(minMagnitude, y1y2[1]), new Scalar(0), 3); } - images[7] = new Img(gradientComb, false).toJfxImage(); - ref = trace("Display gradient comb", ref); + // for (int row = 0; row < rangeDisplay.rows(); row++) + // Imgproc.line(rangeDisplay, new Point(0, row), new Point(magnitudes.get(row).magnitude, row), new Scalar(255)); + images[7] = new Img(rangeDisplay, false).toJfxImage(); + ref = trace("Display ranged magnitudes", ref); Mat vStripColor = new Mat(); Imgproc.cvtColor(vStrip, vStripColor, Imgproc.COLOR_GRAY2BGR); - // vStrip.convertTo(vStripColor, CvType.CV_8UC3); - for (TrajectStep trajectStep : Arrays.stream(houghVtraj).filter(ts -> Math.abs(selectedMagnitudesGradient.get(ts.k)) > 30).collect(Collectors.toList())) { + for (int[] y1y2 : result) { + // for (TrajectStep trajectStep : Arrays.stream(houghVtraj).filter(ts -> Math.abs(magnitudes.get(ts.k).magnitude) > 30).collect(Collectors.toList())) { double mag = stripWidth; - double theta = ((double) trajectStep.theta - 45) / 180 * Math.PI; - int row = trajectStep.k; - Scalar color = (selectedMagnitudesGradient.get(row) >= 0) ? new Scalar(0, 255, 0) : new Scalar(0, 0, 255); + int row = y1y2[0]; + double theta = (magnitudes.get(row).getTheta() - 45) / 180 * Math.PI; + Scalar color = new Scalar(0, 255, 0); Imgproc.line(vStripColor, new Point(vStripColor.width() / 2 - mag * Math.cos(theta), row - mag * Math.sin(theta)), new Point(vStripColor.width() / 2 + mag * Math.cos(theta), row + mag * Math.sin(theta)), color, 1); + color = new Scalar(0, 0, 255); + row = y1y2[1]; + theta = (magnitudes.get(row).getTheta() - 45) / 180 * Math.PI; + Imgproc.line(vStripColor, new Point(vStripColor.width() / 2 - mag * Math.cos(theta), row - mag * Math.sin(theta)), new Point(vStripColor.width() / 2 + mag * Math.cos(theta), row + mag * Math.sin(theta)), color, 1); + } Mat vStripColorDisplay = Mat.zeros(binarized.size(), vStripColor.type()); @@ -270,42 +243,6 @@ private Image[] doWork() { images[8] = new Img(vStripColorDisplay, false).toJfxImage(); ref = trace("Display underlined strip", ref); - // Mat gray = new Mat(); - // houghTransform.convertTo(gray, CvType.CV_8UC1); - // Imgproc.threshold(gray, houghTransform, 0, 255, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU); - // Scalar mean = Core.mean(houghTransform); - // Core.absdiff(houghTransform, mean, houghTransform); - // Imgproc.Sobel(houghTransform, gradient, CvType.CV_64FC1, 0, 1); - // Imgproc.Sobel(houghTransform, gradient, CvType.CV_64FC1, 1, 0); - // Core.absdiff(gradient, new Scalar(0), gradient); - // wImgproc.adaptiveThreshold(gray, houghTransform, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY_INV, 7, 10); - // Core.pow(houghTransform, 4, houghTransform); - // gradient.row(0).setTo(new Scalar(0)); - // gradient.row(houghTransform.rows() - 1).setTo(new Scalar(0)); - // Core.normalize(houghTransform, houghTransform, 0, 255, Core.NORM_MINMAX); - // houghTransform = new Img(houghTransform, false).morphologyEx(Imgproc.MORPH_CLOSE, Imgproc.MORPH_ELLIPSE, new Size(1, 7)).getSrc(); - // Imgproc.threshold(houghTransform, houghTransform, 0, 1, Imgproc.THRESH_TOZERO); - // Core.addWeighted(houghTransform, 0, gradient, 1, 0, houghTransform); - // Core.normalize(houghTransform, houghTransform, 0, 1, Core.NORM_MINMAX); - // Imgproc.threshold(houghTransform, houghTransform, 150, 255, Imgproc.THRESH_BINARY); - // Imgproc.morphologyEx(houghTransform, gradient, Imgproc.MORPH_GRADIENT, Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(1, 2))); - // Function approxHoughVFunction = RadonTransform.approxTraject(houghVtraj); - // for (int y = 0; y < vHoughColor.height(); y++) { - // int x = (int) Math.round(approxHoughVFunction.apply((double) y)); - // if (x < 0) - // x = 0; - // if (x >= vHoughColor.width()) - // x = vHoughColor.width() - 1; - // vHoughColor.put(y, x, 0, 255, 0); - // } - // ref = trace("Fht approx", ref); - // System.out.println(houghTransform); - - // for (Pair pair : RadonTransform.getLocalExtr(houghTransform, 200)) { - // Imgproc.circle(vHoughColor, new Point((Math.atan((pair.point.x - stripWidth + 1) / (stripWidth - 1)) / Math.PI * 180) + 45, pair.point.y), 2, new Scalar(255, 0, 0), -1); - // System.out.println((Math.atan((pair.point.x - stripWidth + 1) / (stripWidth - 1)) / Math.PI * 180) + " " + pair.point.y + " " + pair.value); - // } - Mat vTransform = RadonTransform.radonTransform(vStrip, -45, 45); Mat vProjection = RadonTransform.radonRemap(vTransform, -45); @@ -332,12 +269,11 @@ private Image[] doWork() { } Mat vProjectionColor = Mat.zeros(vProjection.size(), CvType.CV_8UC3); - for (int y = 0; y < vProjectionColor.height(); y++) { - vProjectionColor.put(y, vtraj[y].theta, 0, 0, 255); - if (vtraj[y].magnitude != 0) { + for (int y = 0; y < vProjectionColor.height(); y++) + if (vtraj[y].magnitude != 0) vProjectionColor.put(y, vtraj[y].theta, 255, 0, 0); - } - } + else + vProjectionColor.put(y, vtraj[y].theta, 0, 0, 255); ref = trace("Best traject radon", ref); images[11] = new Img(vProjectionColor, false).toJfxImage(); @@ -358,29 +294,6 @@ private Image[] doWork() { // } // ref = trace("Approx traject radon", ref); - double houghError = 0; - double houghApproxError = 0; - double radonError = 0; - double radonApproxError = 0; - count = 0; - for (int y = 100; y <= 260; y += 80) { - houghError += Math.pow((houghVtraj[y].theta - 45) - angles[count], 2); - // houghApproxError += Math.pow(approxHoughVFunction.apply((double) y) - 45 - angles[count], 2); - radonError += Math.pow((vtraj[y].theta - 45) - angles[count], 2); - // radonApproxError += Math.pow(approxRadonVFunction.apply((double) y) - 45 - angles[count], 2); - count++; - } - houghError = Math.sqrt(houghError); - houghApproxError = Math.sqrt(houghApproxError); - radonError = Math.sqrt(radonError); - radonApproxError = Math.sqrt(radonApproxError); - - System.out.println("Hough : " + houghError); - System.out.println("Hough approx : " + houghApproxError); - - System.out.println("Radon : " + radonError); - System.out.println("Radon approx : " + radonApproxError); - return images; } diff --git a/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo3.java b/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo3.java index 534150bb3..f084a8bce 100644 --- a/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo3.java +++ b/gs-cv/src/main/java/org/genericsystem/cv/application/RadonTransformDemo3.java @@ -1,5 +1,13 @@ package org.genericsystem.cv.application; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + import org.genericsystem.cv.AbstractApp; import org.genericsystem.cv.Img; import org.genericsystem.cv.application.GeneralInterpolator.OrientedPoint; @@ -12,14 +20,6 @@ import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - import javafx.application.Platform; import javafx.scene.image.Image; import javafx.scene.image.ImageView; @@ -119,88 +119,14 @@ private Image[] doWork() { List vHoughs = vStrips.stream().map(strip -> RadonTransform.fastHoughTransform(strip)).collect(Collectors.toList()); List hHoughs = hStrips.stream().map(strip -> RadonTransform.fastHoughTransform(strip)).collect(Collectors.toList()); - vHoughs.stream().forEach(projectionMap -> Imgproc.morphologyEx(projectionMap, projectionMap, Imgproc.MORPH_GRADIENT, Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(1, 2)))); - hHoughs.stream().forEach(projectionMap -> Imgproc.morphologyEx(projectionMap, projectionMap, Imgproc.MORPH_GRADIENT, Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(1, 2)))); - - vHoughs.stream().forEach(projectionMap -> Core.pow(projectionMap, 2, projectionMap)); - hHoughs.stream().forEach(projectionMap -> Core.pow(projectionMap, 2, projectionMap)); - - vHoughs.stream().forEach(projectionMap -> projectionMap.row(0).setTo(new Scalar(0))); - hHoughs.stream().forEach(projectionMap -> projectionMap.row(projectionMap.rows() - 1).setTo(new Scalar(0))); - - // double maxV = vHoughs.stream().mapToDouble(projectionMap -> Core.minMaxLoc(projectionMap).maxVal).max().getAsDouble(); - // double maxH = hHoughs.stream().mapToDouble(projectionMap -> Core.minMaxLoc(projectionMap).maxVal).max().getAsDouble(); - vHoughs.stream().forEach(projectionMap -> { - Mat blur = new Mat(); - Imgproc.blur(projectionMap, blur, new Size(1, 11), new Point(-1, -1), Core.BORDER_ISOLATED); - Core.absdiff(projectionMap, blur, projectionMap); - Core.normalize(projectionMap, projectionMap, 0, 1, Core.NORM_MINMAX); - }); - hHoughs.stream().forEach(projectionMap -> { - Mat blur = new Mat(); - Imgproc.blur(projectionMap, blur, new Size(1, 11), new Point(-1, -1), Core.BORDER_ISOLATED); - Core.absdiff(projectionMap, blur, projectionMap); - Core.normalize(projectionMap, projectionMap, 0, 1, Core.NORM_MINMAX); - }); - - // vHoughs.stream().forEach(projectionMap -> Core.divide(projectionMap, new Scalar(maxV), projectionMap)); - // hHoughs.stream().forEach(projectionMap -> Core.divide(projectionMap, new Scalar(maxH), projectionMap)); - // vHoughs.stream().forEach(projectionMap -> Core.normalize(projectionMap, projectionMap, 0, 1, Core.NORM_MINMAX)); - // hHoughs.stream().forEach(projectionMap -> Core.normalize(projectionMap, projectionMap, 0, 1, Core.NORM_MINMAX)); + vHoughs.stream().forEach(projectionMap -> Core.normalize(projectionMap, projectionMap, 0, 1, Core.NORM_MINMAX)); + hHoughs.stream().forEach(projectionMap -> Core.normalize(projectionMap, projectionMap, 0, 1, Core.NORM_MINMAX)); ref = trace("Compute FHT", ref); - List vHoughTrajs = vHoughs.stream().map(projectionMap -> RadonTransform.bestTrajectFHT(projectionMap, -0.000001)).collect(Collectors.toList()); - List hHoughTrajs = hHoughs.stream().map(projectionMap -> RadonTransform.bestTrajectFHT(projectionMap, -0.000001)).collect(Collectors.toList()); + List> vHoughTrajs = vHoughs.stream().map(projectionMap -> RadonTransform.bestTrajectFHT(projectionMap, 11, -10)).collect(Collectors.toList()); + List> hHoughTrajs = hHoughs.stream().map(projectionMap -> RadonTransform.bestTrajectFHT(projectionMap, 11, -10)).collect(Collectors.toList()); ref = trace("Compute trajects", ref); - for (TrajectStep[] houghVtraj : vHoughTrajs) { - for (int y = 0; y < houghVtraj.length; y++) - houghVtraj[y].theta = (int) Math.round(Math.atan((houghVtraj[y].theta - stripWidth + 1) / (stripWidth - 1)) / Math.PI * 180 + 45); - - for (int y = 0; y < houghVtraj.length; y++) { - if (houghVtraj[y].magnitude == 0) - for (int end = y + 1; end < houghVtraj.length; end++) { - if (houghVtraj[end].magnitude != 0) { - for (int current = y; current < end; current++) - houghVtraj[current].theta = houghVtraj[y == 0 ? 0 : y - 1].theta + (houghVtraj[end].theta - houghVtraj[y == 0 ? 0 : y - 1].theta) * (current - y) / (end - y + 1); - y = end; - break; - } - } - } - } - - for (TrajectStep[] houghHtraj : hHoughTrajs) { - for (int y = 0; y < houghHtraj.length; y++) - houghHtraj[y].theta = (int) Math.round(Math.atan((houghHtraj[y].theta - stripHeight + 1) / (stripHeight - 1)) / Math.PI * 180 + 45); - - for (int y = 0; y < houghHtraj.length; y++) { - if (houghHtraj[y].magnitude == 0) - for (int end = y + 1; end < houghHtraj.length; end++) { - if (houghHtraj[end].magnitude != 0) { - for (int current = y; current < end; current++) - houghHtraj[current].theta = houghHtraj[y == 0 ? 0 : y - 1].theta + (houghHtraj[end].theta - houghHtraj[y == 0 ? 0 : y - 1].theta) * (current - y) / (end - y + 1); - y = end; - break; - } - } - } - } - - ref = trace("Transform trajects", ref); - // - // List> approxVFHTFunctions = vHoughTrajs.stream().map(traj -> RadonTransform.approxTraject(traj)).collect(Collectors.toList()); - // List> approxHFHTFunctions = hHoughTrajs.stream().map(traj -> RadonTransform.approxTraject(traj)).collect(Collectors.toList()); - // - // ref = trace("Compute approxs", ref); - - // List fhtHorizontals = new ArrayList<>(); - // for (int vStrip = 0; vStrip < approxVFHTFunctions.size(); vStrip++) - // fhtHorizontals.addAll(RadonTransform.toHorizontalOrientedPoints(approxVFHTFunctions.get(vStrip), (vStrip + 1) * vStep, binarized.height(), hStep)); - // List fhtVerticals = new ArrayList<>(); - // for (int hStrip = 0; hStrip < approxHFHTFunctions.size(); hStrip++) - // fhtVerticals.addAll(RadonTransform.toVerticalOrientedPoints(approxHFHTFunctions.get(hStrip), (hStrip + 1) * hStep, binarized.width(), vStep)); - List fhtHorizontals = new ArrayList<>(); for (int vStripIndex = 0; vStripIndex < vHoughTrajs.size(); vStripIndex++) fhtHorizontals.addAll(RadonTransform.toHorizontalOrientedPoints(vHoughTrajs.get(vStripIndex), (vStripIndex + 1) * vStep)); diff --git a/gs-cv/src/main/java/org/genericsystem/cv/application/TrajectStep.java b/gs-cv/src/main/java/org/genericsystem/cv/application/TrajectStep.java index b2136bc32..b23c588d3 100644 --- a/gs-cv/src/main/java/org/genericsystem/cv/application/TrajectStep.java +++ b/gs-cv/src/main/java/org/genericsystem/cv/application/TrajectStep.java @@ -1,6 +1,6 @@ package org.genericsystem.cv.application; -class TrajectStep implements Comparable { +public class TrajectStep implements Comparable { public final int k; public int theta; public final double magnitude;