Skip to content

Commit

Permalink
Merge pull request #524 from saalfeldlab/feat/samWithBox
Browse files Browse the repository at this point in the history
initial implementation of Segment Anything with box prompt
  • Loading branch information
cmhulbert authored Jan 23, 2024
2 parents b754fa7 + 3c2b4b8 commit d659d66
Show file tree
Hide file tree
Showing 34 changed files with 1,166 additions and 641 deletions.
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<groupId>org.janelia.saalfeldlab</groupId>
<artifactId>paintera</artifactId>
<version>1.0.2-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>

<name>Paintera</name>
<description>New Era Painting and annotation tool</description>
Expand Down Expand Up @@ -53,7 +53,7 @@
<javadoc.skip>true</javadoc.skip>
<maven.javadoc.skip>${javadoc.skip}</maven.javadoc.skip>

<saalfx.version>1.0.0</saalfx.version>
<saalfx.version>1.1.0</saalfx.version>

<janino.version>3.0.7</janino.version>
<logback.version>1.4.0</logback.version>
Expand Down Expand Up @@ -809,8 +809,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<source>10</source>
<target>10</target>
</configuration>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/bdv/fx/viewer/ViewerPanelFX.java
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,13 @@ public ReadOnlyDoubleProperty getMouseYProperty() {
return mouseTracker.getMouseYProperty();
}

/**
*
* Creates a ObservablePosition which refers to either the location on ViewerPanelFX under the mouse, OR the center
* if the mouse is not on the ViewerPanelFX.
*
* @return the observable position
*/
public ObservablePosition createMousePositionOrCenterBinding() {

var xBinding = Bindings.createDoubleBinding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ public <D, T> void addGenericState(final SourceState<D, T> state) {
* @param <T> Viewer type of {@code state}
* @return the {@link ConnectomicsRawState} that was built from the inputs and added to the viewer
*/
public <D extends RealType<D> & NativeType<D>, T extends AbstractVolatileNativeRealType<D, T>> ConnectomicsRawState<D, T> addConnectomicsRawSource(
public <D extends RealType<D> & NativeType<D>, T extends AbstractVolatileNativeRealType<D, T>> ConnectomicsRawState<D, T> addMultiscaleConnectomicsRawSource(
final RandomAccessibleInterval<D>[] data,
final double[][] resolution,
final double[][] offset,
Expand Down Expand Up @@ -413,7 +413,7 @@ public <D extends RealType<D> & NativeType<D>, T extends AbstractVolatileNativeR
final double max,
final String name) {

return addConnectomicsRawSource(
return addMultiscaleConnectomicsRawSource(
new RandomAccessibleInterval[]{data},
new double[][]{resolution},
new double[][]{offset},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ public enum PaintActionType implements ActionType {
Intersect,
SetBrushSize,
SetBrushDepth,
ShapeInterpolation;
ShapeInterpolation,
SegmentAnything;

public static EnumSet<PaintActionType> of(final PaintActionType first, final PaintActionType... rest) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import javafx.beans.property.SimpleDoubleProperty;

/* TODO: Using this for all speed modifier, not just rotation; should rename, but will require serialization changes. */
public class ButtonRotationSpeedConfig {

private static final double DEFAULT_SLOW = 0.5;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
package org.janelia.saalfeldlab.paintera.control.navigation;

import javafx.beans.binding.DoubleExpression;
import javafx.util.Duration;
import net.imglib2.realtransform.AffineTransform3D;
import org.janelia.saalfeldlab.paintera.state.GlobalTransformManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.function.Consumer;
import java.lang.invoke.MethodHandles;

public class Rotate {

private static final double ROTATION_STEP = Math.PI / 180;
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private final DoubleExpression speed;
private static final double DEFAULT_STEP = Math.PI / 180;
private double speed = 1.0;

private final AffineTransform3D globalTransform = new AffineTransform3D();

private final AffineTransformWithListeners displayTransformUpdater;

private final AffineTransformWithListeners globalToViewerTransformUpdater;

private final Consumer<AffineTransform3D> submitTransform;

private final GlobalTransformManager manager;

private final AffineTransform3D affineDragStart = new AffineTransform3D();
Expand All @@ -33,29 +34,32 @@ public class Rotate {
private final AffineTransform3D globalToViewerTransform = new AffineTransform3D();

private final AffineTransform3D displayTransform = new AffineTransform3D();
private boolean busy = false;

public Rotate(
final DoubleExpression speed,
final AffineTransformWithListeners displayTransformUpdater,
final AffineTransformWithListeners globalToViewerTransformUpdater,
final GlobalTransformManager globalTransformManager,
final Consumer<AffineTransform3D> submitTransform) {
final GlobalTransformManager globalTransformManager) {

super();
this.speed = speed;

this.globalTransformTracker = new TranslationController.TransformTracker(globalTransform, globalTransformManager);
this.globalToViewerTransformTracker = new TranslationController.TransformTracker(globalToViewerTransform, globalTransformManager);
this.displayTransformTracker = new TranslationController.TransformTracker(displayTransform, globalTransformManager);

this.displayTransformUpdater = displayTransformUpdater;
this.globalToViewerTransformUpdater = globalToViewerTransformUpdater;
this.submitTransform = submitTransform;
this.manager = globalTransformManager;
listenOnTransformChanges();
}

public void initialize() {
public void setSpeed(double speed) {
this.speed = speed;
}



public void initialize(final double displayStartX, final double displayStartY) {

synchronized (manager) {
affineDragStart.set(globalTransform);
Expand All @@ -76,44 +80,78 @@ public void stopListeningOnTransformChanges() {
this.globalToViewerTransformUpdater.removeListener(this.globalToViewerTransformTracker);
}

public void rotate(final double x, final double y, final double startX, final double startY) {
public enum Axis {
X, Y, Z
}

public synchronized void rotateAroundAxis(final double x, final double y, final Axis axis) {
if (busy) return;

final AffineTransform3D concatenated = displayTransform.copy()
.concatenate(globalToViewerTransform)
.concatenate(globalTransform);

concatenated.set(concatenated.get(0, 3) - x, 0, 3);
concatenated.set(concatenated.get(1, 3) - y, 1, 3);

final var step = speed * DEFAULT_STEP;
LOG.debug("Rotating {} around axis={} by angley={}", concatenated, axis, step);
concatenated.rotate(axis.ordinal(), step);
concatenated.set(concatenated.get(0, 3) + x, 0, 3);
concatenated.set(concatenated.get(1, 3) + y, 1, 3);

final AffineTransform3D rotatedTransform = displayTransform.copy()
.concatenate(globalToViewerTransform)
.inverse()
.concatenate(concatenated);

final double magnitude = Math.abs(speed);
if (magnitude > 1) {
busy = true;
manager.setTransform(rotatedTransform, Duration.millis(Math.log10(magnitude) * 100), () -> this.busy = false);
} else {
manager.setTransform(rotatedTransform);
}
}

public void rotate3D(final double x, final double y, final double startX, final double startY) {

final AffineTransform3D affine = new AffineTransform3D();
final AffineTransform3D rotated = new AffineTransform3D();
synchronized (manager) {
final double v = ROTATION_STEP * this.speed.get();
affine.set(affineDragStart);
final double[] point = new double[]{x, y, 0};
final double[] origin = new double[]{startX, startY, 0};
final double v = DEFAULT_STEP * this.speed;
rotated.set(affineDragStart);
final double[] start = new double[]{startX, startY, 0};
final double[] end = new double[]{x, y, 0};

displayTransform.applyInverse(point, point);
displayTransform.applyInverse(origin, origin);
displayTransform.applyInverse(end, end);
displayTransform.applyInverse(start, start);

final double[] delta = new double[]{point[0] - origin[0], point[1] - origin[1], 0};
final double[] delta = new double[]{end[0] - start[0], end[1] - start[1], 0};
// TODO do scaling separately. need to swap .get( 0, 0 ) and
// .get( 1, 1 ) ?
final double[] rotation = new double[]{
delta[1] * v * displayTransform.get(0, 0),
-delta[0] * v * displayTransform.get(1, 1),
0};

globalToViewerTransform.applyInverse(origin, origin);
globalToViewerTransform.applyInverse(start, start);
globalToViewerTransform.applyInverse(rotation, rotation);

// center shift
for (int d = 0; d < origin.length; ++d) {
affine.set(affine.get(d, 3) - origin[d], d, 3);
for (int d = 0; d < start.length; ++d) {
rotated.set(rotated.get(d, 3) - start[d], d, 3);
}

for (int d = 0; d < rotation.length; ++d) {
affine.rotate(d, rotation[d]);
rotated.rotate(d, rotation[d]);
}

// center un-shift
for (int d = 0; d < origin.length; ++d) {
affine.set(affine.get(d, 3) + origin[d], d, 3);
for (int d = 0; d < start.length; ++d) {
rotated.set(rotated.get(d, 3) + start[d], d, 3);
}

submitTransform.accept(affine);
manager.setTransform(rotated);
}
}
}
Loading

0 comments on commit d659d66

Please sign in to comment.