diff --git a/core/src/main/java/edu/wpi/grip/core/operations/Operations.java b/core/src/main/java/edu/wpi/grip/core/operations/Operations.java index 37a2bd7fd6..0c4b8a6d93 100644 --- a/core/src/main/java/edu/wpi/grip/core/operations/Operations.java +++ b/core/src/main/java/edu/wpi/grip/core/operations/Operations.java @@ -6,6 +6,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.name.Named; +import edu.wpi.grip.core.OperationDescription; import edu.wpi.grip.core.OperationMetaData; import edu.wpi.grip.core.events.OperationAddedEvent; import edu.wpi.grip.core.operations.composite.*; @@ -21,9 +22,15 @@ import edu.wpi.grip.core.operations.opencv.MinMaxLoc; import edu.wpi.grip.core.operations.opencv.NewPointOperation; import edu.wpi.grip.core.operations.opencv.NewSizeOperation; +import edu.wpi.grip.core.operations.templated.TemplateFactory; import edu.wpi.grip.core.sockets.InputSocket; import edu.wpi.grip.core.sockets.OutputSocket; +import edu.wpi.grip.core.sockets.SocketHint; +import edu.wpi.grip.core.sockets.SocketHints; +import edu.wpi.grip.core.util.Icon; +import org.bytedeco.javacpp.opencv_core.Mat; import org.bytedeco.javacpp.opencv_core.Point; +import org.bytedeco.javacpp.opencv_core.Rect; import org.bytedeco.javacpp.opencv_core.Size; import static com.google.common.base.Preconditions.checkNotNull; @@ -44,6 +51,8 @@ public class Operations { this.eventBus = checkNotNull(eventBus, "EventBus cannot be null"); checkNotNull(ntPublisherFactory, "ntPublisherFactory cannot be null"); checkNotNull(rosPublishFactory, "rosPublishFactory cannot be null"); + TemplateFactory templateFactory = new TemplateFactory(isf, osf); + this.operations = ImmutableList.of( // Composite operations new OperationMetaData(BlurOperation.DESCRIPTION, () -> new BlurOperation(isf, osf)), @@ -67,6 +76,52 @@ public class Operations { new OperationMetaData(WatershedOperation.DESCRIPTION, () -> new WatershedOperation(isf, osf)), new OperationMetaData(ThresholdMoving.DESCRIPTION, () -> new ThresholdMoving(isf, osf)), + new OperationMetaData( + OperationDescription.builder() + .name("Crop") + .summary("Crop an image") + .icon(Icon.iconStream("grip")) + .build(), + templateFactory.create( + SocketHints.Inputs.createMatSocketHint("src", false), + SocketHints.Inputs.createPointSocketHint("p1", false), + SocketHints.Inputs.createPointSocketHint("p2", false), + SocketHints.Inputs.createMatSocketHint("dst", true), + (src, p1, p2, dst) -> { + final Rect rect = new Rect(p1, p2); + final Mat tmp = new Mat(src, rect); + tmp.copyTo(dst); + } + )), + + new OperationMetaData( + OperationDescription.builder() + .name("Number Threshold") + .summary("Returns a boolean on whether or not the number is within the given range.") + .icon(Icon.iconStream("grip")) + .build(), + templateFactory.createReturning( + SocketHints.Inputs.createNumberSpinnerSocketHint("Input", 0), + SocketHints.Inputs.createNumberSpinnerSocketHint("Min", -1), + SocketHints.Inputs.createNumberSpinnerSocketHint("Max", 1), + SocketHints.Outputs.createBooleanSocketHint("Output", true), + (num, min, max) -> min.doubleValue() <= num.doubleValue() && max.doubleValue() >= num.doubleValue() + ) + ), + + new OperationMetaData( + OperationDescription.builder() + .name("Count Contours") + .summary("Counts the number of contours in a contours report.") + .icon(Icon.iconStream("grip")) + .build(), + templateFactory.createReturning( + new SocketHint.Builder<>(ContoursReport.class).identifier("Contours").build(), + SocketHints.Outputs.createNumberSocketHint("Count", 0), + (contours) -> contours.getContours().size() + ) + ), + // OpenCV operations new OperationMetaData(MatFieldAccessor.DESCRIPTION, () -> new MatFieldAccessor(isf, osf)), new OperationMetaData(MinMaxLoc.DESCRIPTION, () -> new MinMaxLoc(isf, osf)), diff --git a/core/src/main/java/edu/wpi/grip/core/operations/templated/OneSourceReturnDestinationOperation.java b/core/src/main/java/edu/wpi/grip/core/operations/templated/OneSourceReturnDestinationOperation.java new file mode 100644 index 0000000000..c57f29ad97 --- /dev/null +++ b/core/src/main/java/edu/wpi/grip/core/operations/templated/OneSourceReturnDestinationOperation.java @@ -0,0 +1,49 @@ +package edu.wpi.grip.core.operations.templated; + + +import com.google.common.collect.ImmutableList; +import edu.wpi.grip.core.Operation; +import edu.wpi.grip.core.sockets.InputSocket; +import edu.wpi.grip.core.sockets.OutputSocket; +import edu.wpi.grip.core.sockets.SocketHint; + +import java.util.List; + +@SuppressWarnings("PMD.GenericsNaming") +class OneSourceReturnDestinationOperation implements Operation { + private final InputSocket input1; + private final OutputSocket output; + private final Performer performer; + + @FunctionalInterface + public interface Performer { + R perform(T1 src1); + } + + OneSourceReturnDestinationOperation(InputSocket.Factory inputSocketFactory, + OutputSocket.Factory outputSocketFactory, + SocketHint t1SocketHint, + SocketHint rSocketHint, + Performer performer) { + this.input1 = inputSocketFactory.create(t1SocketHint); + this.output = outputSocketFactory.create(rSocketHint); + assert output.getValue().isPresent() : TemplateFactory.ASSERTION_MESSAGE; + this.performer = performer; + } + + @Override + public List getInputSockets() { + return ImmutableList.of(input1); + } + + @Override + public List getOutputSockets() { + return ImmutableList.of(output); + } + + @Override + @SuppressWarnings("OptionalGetWithoutIsPresent") + public void perform() { + output.setValue(performer.perform(input1.getValue().get())); + } +} diff --git a/core/src/main/java/edu/wpi/grip/core/operations/templated/TemplateFactory.java b/core/src/main/java/edu/wpi/grip/core/operations/templated/TemplateFactory.java index 332dcab626..09961c8952 100644 --- a/core/src/main/java/edu/wpi/grip/core/operations/templated/TemplateFactory.java +++ b/core/src/main/java/edu/wpi/grip/core/operations/templated/TemplateFactory.java @@ -101,6 +101,22 @@ public Supplier create( return () -> new SevenSourceOneDestinationOperation<>(isf, osf, t1SocketHint, t2SocketHint, t3SocketHint, t4SocketHint, t5SocketHint, t6SocketHint, t7SocketHint, rSocketHint, performer); } + public Supplier createReturning( + SocketHint t1SocketHint, + SocketHint rSocketHint, + OneSourceReturnDestinationOperation.Performer performer) { + return () -> new OneSourceReturnDestinationOperation<>(isf, osf, t1SocketHint, rSocketHint, performer); + } + + public Supplier createReturning( + SocketHint t1SocketHint, + SocketHint t2SocketHint, + SocketHint t3SocketHint, + SocketHint rSocketHint, + ThreeSourceReturnDestinationOperation.Performer performer) { + return () -> new ThreeSourceReturnDestinationOperation<>(isf, osf, t1SocketHint, t2SocketHint, t3SocketHint, rSocketHint, performer); + } + public Supplier createAllMatTwoSource( SocketHint matSocketHint, SocketHint matSocketHint2, diff --git a/core/src/main/java/edu/wpi/grip/core/operations/templated/ThreeSourceReturnDestinationOperation.java b/core/src/main/java/edu/wpi/grip/core/operations/templated/ThreeSourceReturnDestinationOperation.java new file mode 100644 index 0000000000..17bfc6c87f --- /dev/null +++ b/core/src/main/java/edu/wpi/grip/core/operations/templated/ThreeSourceReturnDestinationOperation.java @@ -0,0 +1,59 @@ +package edu.wpi.grip.core.operations.templated; + + +import com.google.common.collect.ImmutableList; +import edu.wpi.grip.core.Operation; +import edu.wpi.grip.core.sockets.InputSocket; +import edu.wpi.grip.core.sockets.OutputSocket; +import edu.wpi.grip.core.sockets.SocketHint; + +import java.util.List; + +@SuppressWarnings("PMD.GenericsNaming") +class ThreeSourceReturnDestinationOperation implements Operation { + private final InputSocket input1; + private final InputSocket input2; + private final InputSocket input3; + private final OutputSocket output; + private final Performer performer; + + @FunctionalInterface + public interface Performer { + R perform(T1 src1, T2 src2, T3 src3); + } + + ThreeSourceReturnDestinationOperation( + InputSocket.Factory inputSocketFactory, + OutputSocket.Factory outputSocketFactory, + SocketHint t1SocketHint, + SocketHint t2SocketHint, + SocketHint t3SocketHint, + SocketHint rSocketHint, + Performer performer) { + this.performer = performer; + this.input1 = inputSocketFactory.create(t1SocketHint); + this.input2 = inputSocketFactory.create(t2SocketHint); + this.input3 = inputSocketFactory.create(t3SocketHint); + this.output = outputSocketFactory.create(rSocketHint); + assert output.getValue().isPresent() : TemplateFactory.ASSERTION_MESSAGE; + } + + @Override + public List getInputSockets() { + return ImmutableList.of(input1, input2, input3); + } + + @Override + public List getOutputSockets() { + return ImmutableList.of(output); + } + + @Override + @SuppressWarnings("OptionalGetWithoutIsPresent") + public void perform() { + output.setValue(performer.perform( + input1.getValue().get(), + input2.getValue().get(), + input3.getValue().get())); + } +}