From e5136646d32b2c9329dc511364acb454721e6174 Mon Sep 17 00:00:00 2001 From: tpietzsch Date: Sat, 18 Oct 2025 14:26:30 +0200 Subject: [PATCH 1/4] fix errors --- pom.xml | 2 +- .../net/preibisch/bigstitcher/spark/SparkAffineFusion.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index f34a7f3..01466cf 100644 --- a/pom.xml +++ b/pom.xml @@ -97,7 +97,7 @@ 1.0.0-beta-36 --> 7.1.4 - 0.18.0 + 0.18.2 10.6.4 2.3.5 7.0.5 diff --git a/src/main/java/net/preibisch/bigstitcher/spark/SparkAffineFusion.java b/src/main/java/net/preibisch/bigstitcher/spark/SparkAffineFusion.java index cfec333..dc62e11 100644 --- a/src/main/java/net/preibisch/bigstitcher/spark/SparkAffineFusion.java +++ b/src/main/java/net/preibisch/bigstitcher/spark/SparkAffineFusion.java @@ -52,6 +52,7 @@ import net.imglib2.FinalInterval; import net.imglib2.Interval; import net.imglib2.RandomAccessibleInterval; +import net.imglib2.algorithm.blocks.BlockAlgoUtils; import net.imglib2.algorithm.blocks.BlockSupplier; import net.imglib2.converter.Converter; import net.imglib2.converter.RealUnsignedByteConverter; @@ -558,7 +559,7 @@ else if ( dataType == DataType.UINT16 ) } //final RandomAccessibleInterval img; - final BlockSupplier blockSupplier; + final BlockSupplier< ? > blockSupplier; final FinalInterval interval = new FinalInterval( bbMin, bbMax ); if ( masks ) @@ -605,6 +606,7 @@ else if ( dataType == DataType.UINT16 ) registrations, dataLocal.getSequenceDescription().getViewDescriptions(), fusionType,//fusion.getFusionType(), + Double.NaN, null, // map will go here 1, // linear interpolation coefficients, // intensity correction @@ -622,7 +624,7 @@ else if ( dataType == DataType.UINT16 ) blockMax[ d ] = Math.min( Intervals.zeroMin( interval ).max( d ), blockMin[ d ] + gridBlock[1][ d ] - 1 ); final RandomAccessibleInterval image; - final RandomAccessibleInterval img = BlkAffineFusion.arrayImg( blockSupplier, new FinalInterval( blockMin, blockMax ) ); + final RandomAccessibleInterval img = BlockAlgoUtils.arrayImg( blockSupplier, new FinalInterval( blockMin, blockMax ) ); // 5D OME-ZARR CONTAINER if ( storageType == StorageFormat.ZARR ) From bcf4b8f3dd3a4e426d59a44a5728a26cbb8a3d79 Mon Sep 17 00:00:00 2001 From: tpietzsch Date: Sat, 18 Oct 2025 14:29:06 +0200 Subject: [PATCH 2/4] Add histogram matching to SparkIntensityMatching Use --method HISTOGRAM command line switch --- pom.xml | 2 +- .../spark/SparkIntensityMatching.java | 32 +++++++++++++++---- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 01466cf..e1de456 100644 --- a/pom.xml +++ b/pom.xml @@ -100,7 +100,7 @@ 0.18.2 10.6.4 2.3.5 - 7.0.5 + 7.0.8-SNAPSHOT 2.5.0 2.3.0 diff --git a/src/main/java/net/preibisch/bigstitcher/spark/SparkIntensityMatching.java b/src/main/java/net/preibisch/bigstitcher/spark/SparkIntensityMatching.java index c3611f3..1ffbf47 100644 --- a/src/main/java/net/preibisch/bigstitcher/spark/SparkIntensityMatching.java +++ b/src/main/java/net/preibisch/bigstitcher/spark/SparkIntensityMatching.java @@ -34,6 +34,11 @@ public class SparkIntensityMatching extends AbstractSelectableViews { + public enum IntensityMatchingMethod + { + RANSAC, HISTOGRAM + } + @Option(names = { "--numCoefficients" }, description = "number of coefficients per dimension (default: 8,8,8)") private String numCoefficientsString = "8,8,8"; @@ -52,19 +57,23 @@ public class SparkIntensityMatching extends AbstractSelectableViews @Option(names = { "--minNumCandidates" }, description = "minimum number of (non-discarded) overlapping pixels required to match overlapping coefficient regions (default: 1000)") private int minNumCandidates = 1000; + @Option(names = {"--method"}, defaultValue = "RANSAC", showDefaultValue = CommandLine.Help.Visibility.ALWAYS, + description = "Method to match intensities between overlapping views: RANSAC or HISTOGRAM") + private IntensityMatchingMethod intensityMatchingMethod; + @CommandLine.Option(names = { "--numIterations" }, description = "number of RANSAC iterations (default: 1000)") private int iterations = 1000; - @CommandLine.Option(names = { "--maxEpsilon" }, description = "maximal allowed transfer error (default: 5.1)") + @CommandLine.Option(names = { "--maxEpsilon" }, description = "maximal allowed transfer error (default: 5.1, only for RANSAC method)") private double maxEpsilon = 0.02 * 255; - @CommandLine.Option(names = { "--minInlierRatio" }, description = "minimal ratio of of inliers to number of candidates (default: 0.1)") + @CommandLine.Option(names = { "--minInlierRatio" }, description = "minimal ratio of of inliers to number of candidates (default: 0.1, only for RANSAC method)") private double minInlierRatio = 0.1; - @CommandLine.Option(names = { "--minNumInliers" }, description = "minimally required absolute number of inliers (default: 10)") + @CommandLine.Option(names = { "--minNumInliers" }, description = "minimally required absolute number of inliers (default: 10, only for RANSAC method)") private int minNumInliers = 10; - @CommandLine.Option(names = { "--maxTrust" }, description = "reject candidates with a cost larger than maxTrust * median cost (default: 3)") + @CommandLine.Option(names = { "--maxTrust" }, description = "reject candidates with a cost larger than maxTrust * median cost (default: 3, only for RANSAC method)") private double maxTrust = 3.0; private SpimData2 dataGlobal; @@ -100,6 +109,7 @@ public Void call() throws Exception final double minInlierRatio = this.minInlierRatio; final int minNumInliers = this.minNumInliers; final double maxTrust = this.maxTrust; + final IntensityMatchingMethod method = this.intensityMatchingMethod; new ViewPairCoefficientMatchesIO( outputURI ).writeCoefficientsSize( coefficientsSize ); @@ -156,8 +166,18 @@ public Void call() throws Exception viewPairRDD.foreach( views -> { final SpimData2 dataLocal = Spark.getSparkJobSpimData2( xmlURI ); System.out.println( "(" + new Date( System.currentTimeMillis() ) + "): " + views._1().getViewSetupId() + "<>" + views._2().getViewSetupId() ); - final ViewPairCoefficientMatches matches = IntensityCorrection.match( dataLocal, views._1(), views._2(), renderScale, coefficientsSize, - minIntensityThreshold, maxIntensityThreshold, minNumCandidates, iterations, maxEpsilon, minInlierRatio, minNumInliers, maxTrust ); + + final ViewPairCoefficientMatches matches; + if ( method == IntensityMatchingMethod.RANSAC ) + { + matches = IntensityCorrection.matchRansac( dataLocal, views._1(), views._2(), renderScale, coefficientsSize, + minIntensityThreshold, maxIntensityThreshold, minNumCandidates, iterations, maxEpsilon, minInlierRatio, minNumInliers, maxTrust ); + } + else // method == IntensityMatchingMethod.HISTOGRAM + { + matches = IntensityCorrection.matchHistograms( dataLocal, views._1(), views._2(), renderScale, coefficientsSize, + minIntensityThreshold, maxIntensityThreshold, minNumCandidates ); + } final ViewPairCoefficientMatchesIO matchWriter = new ViewPairCoefficientMatchesIO(outputURI); matchWriter.write( matches ); } ); From 70d18765857233cebaa51272bb3c396ded72e070 Mon Sep 17 00:00:00 2001 From: Stephan Preibisch Date: Wed, 22 Oct 2025 09:51:30 -0400 Subject: [PATCH 3/4] update versions and shade javax.annotation-api in n5-google-cloud --- pom.xml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index e1de456..8e2e35b 100644 --- a/pom.xml +++ b/pom.xml @@ -96,11 +96,14 @@ 10.6.1 1.0.0-beta-36 --> - 7.1.4 + 8.0.0 + 1.0.0-beta-20 0.18.2 - 10.6.4 + 10.6.5 + 1.0.2 + 2.3.5 - 7.0.8-SNAPSHOT + 8.0.0 2.5.0 2.3.0 @@ -284,6 +287,11 @@ ome formats-gpl + + + javax.annotation + javax.annotation-api + From 20b39ba4cab4c13297d8f3c431a7192dc120e255 Mon Sep 17 00:00:00 2001 From: Stephan Preibisch Date: Wed, 22 Oct 2025 10:01:27 -0400 Subject: [PATCH 4/4] support multiconsensus matching and fix minNumInliers --- .../SparkGeometricDescriptorMatching.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/preibisch/bigstitcher/spark/SparkGeometricDescriptorMatching.java b/src/main/java/net/preibisch/bigstitcher/spark/SparkGeometricDescriptorMatching.java index ae95be0..ad4103c 100644 --- a/src/main/java/net/preibisch/bigstitcher/spark/SparkGeometricDescriptorMatching.java +++ b/src/main/java/net/preibisch/bigstitcher/spark/SparkGeometricDescriptorMatching.java @@ -139,10 +139,13 @@ public enum Method { FAST_ROTATION, FAST_TRANSLATION, PRECISE_TRANSLATION, ICP } @Option(names = { "-rmir", "--ransacMinInlierRatio" }, description = "ransac min inlier ratio (default: 0.1)") protected Double ransacMinInlierRatio = 0.1; - @Option(names = { "-rmif", "--ransacMinInlierFactor" }, description = "ransac min inlier factor, i.e. how many time the minimal number of matches need to found, e.g. affine needs 4 matches, 3x means at least 12 matches required (default: 3.0)") - protected Double ransacMinInlierFactor = 3.0; + @Option(names = { "-rmni", "--ransacMinNumInliers" }, description = "ransac minimal number of required inliers (default: 12)") + protected Integer ransacMinNumInliers = 12; + + @Option(names = { "-rmc", "--ransacMultiConsensus" }, description = "ransac perform multiconsensus matching (default: false)") + protected boolean ransacMultiConsensus = false; + - @Option(names = { "-ime", "--icpMaxError" }, description = "ICP max error in pixels (default: 5.0)") protected Double icpMaxError = 5.0; @@ -220,7 +223,8 @@ else if ( ransacIterations == null ) final int ransacIterations = this.ransacIterations; final double ransacMaxEpsilon = this.ransacMaxError; final double ransacMinInlierRatio = this.ransacMinInlierRatio; - final double ransacMinInlierFactor = this.ransacMinInlierFactor; + final int ransacMinNumInliers = this.ransacMinNumInliers; + final boolean ransacMultiConsensus = this.ransacMultiConsensus; final double icpMaxError = this.icpMaxError; final int icpMaxIterations = this.icpIterations; final boolean icpUseRANSAC = this.icpUseRANSAC; @@ -300,7 +304,7 @@ else if ( ransacIterations == null ) System.out.println( Group.pvid( element.getKey() ) + ", '" + subElement.getKey() + "' : " + subElement.getValue().size() ); } - final RANSACParameters rp = new RANSACParameters( (float)ransacMaxEpsilon, (float)ransacMinInlierRatio, (float)ransacMinInlierFactor, ransacIterations ); + final RANSACParameters rp = new RANSACParameters( (float)ransacMaxEpsilon, (float)ransacMinInlierRatio, ransacMinNumInliers, ransacIterations, ransacMultiConsensus ); final Model< ? > model = createModelInstance(transformationModel, regularizationModel, lambda); final MatcherPairwise< InterestPoint > matcher = createMatcherInstance( @@ -424,7 +428,7 @@ else if ( ransacIterations == null ) groupedInterestpoints.put( task.vB, ipGrouping.group( task.vB ) ); IOFunctions.println( task.vA + " <=> " + task.vB + ": Grouping interestpoints for " + task.vB + " (" + ipGrouping.countBefore() + " >>> " + ipGrouping.countAfter() + ")" ); - final RANSACParameters rp = new RANSACParameters( (float)ransacMaxEpsilon, (float)ransacMinInlierRatio, (float)ransacMinInlierFactor, ransacIterations ); + final RANSACParameters rp = new RANSACParameters( (float)ransacMaxEpsilon, (float)ransacMinInlierRatio, ransacMinNumInliers, ransacIterations, ransacMultiConsensus ); final Model< ? > model = createModelInstance(transformationModel, regularizationModel, lambda); final MatcherPairwise< GroupedInterestPoint< ViewId > > matcher = createMatcherInstance( @@ -609,7 +613,7 @@ else if ( registrationMethod == Method.PRECISE_TRANSLATION ) rp.getMinInlierRatio(), rp.getMaxEpsilon(), rp.getNumIterations(), - Math.round( rp.getMinInlierFactor() * model.getMinNumMatches() ) ); + rp.getMinNumMatches() ); matcher = new IterativeClosestPointPairwise<>( ip ); }