Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions core/src/main/java/edu/wpi/grip/core/operations/Operations.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand All @@ -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;
Expand All @@ -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)),
Expand All @@ -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),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this make the dst an Input?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. But the Crop operation should be in its own class file like every other custom operation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait... SocketHints.Inputs.createMatSocketHint() can be used to create a socket hint used for an output? Isn't that a bit misleading?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. SocketHints needs an overhaul (and Javadocs).

Copy link
Member Author

@JLLeitschuh JLLeitschuh Aug 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How so? What are you thinking about this? I agree with needing an overhaul but I want to know what your thoughts are. This overhaul needs to be done before we expose python bindings.
Open an issue and we can discuss that there.

(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)),
Expand Down
Original file line number Diff line number Diff line change
@@ -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<T1, R> implements Operation {
private final InputSocket<T1> input1;
private final OutputSocket<R> output;
private final Performer<T1, R> performer;

@FunctionalInterface
public interface Performer<T1, R> {
R perform(T1 src1);
}

OneSourceReturnDestinationOperation(InputSocket.Factory inputSocketFactory,
OutputSocket.Factory outputSocketFactory,
SocketHint<T1> t1SocketHint,
SocketHint<R> rSocketHint,
Performer<T1, R> performer) {
this.input1 = inputSocketFactory.create(t1SocketHint);
this.output = outputSocketFactory.create(rSocketHint);
assert output.getValue().isPresent() : TemplateFactory.ASSERTION_MESSAGE;
this.performer = performer;
}

@Override
public List<InputSocket> getInputSockets() {
return ImmutableList.of(input1);
}

@Override
public List<OutputSocket> getOutputSockets() {
return ImmutableList.of(output);
}

@Override
@SuppressWarnings("OptionalGetWithoutIsPresent")
public void perform() {
output.setValue(performer.perform(input1.getValue().get()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ public <T1, T2, T3, T4, T5, T6, T7, R> Supplier<Operation> create(
return () -> new SevenSourceOneDestinationOperation<>(isf, osf, t1SocketHint, t2SocketHint, t3SocketHint, t4SocketHint, t5SocketHint, t6SocketHint, t7SocketHint, rSocketHint, performer);
}

public <T1, R> Supplier<Operation> createReturning(
SocketHint<T1> t1SocketHint,
SocketHint<R> rSocketHint,
OneSourceReturnDestinationOperation.Performer<T1, R> performer) {
return () -> new OneSourceReturnDestinationOperation<>(isf, osf, t1SocketHint, rSocketHint, performer);
}

public <T1, T2, T3, R> Supplier<Operation> createReturning(
SocketHint<T1> t1SocketHint,
SocketHint<T2> t2SocketHint,
SocketHint<T3> t3SocketHint,
SocketHint<R> rSocketHint,
ThreeSourceReturnDestinationOperation.Performer<T1, T2, T3, R> performer) {
return () -> new ThreeSourceReturnDestinationOperation<>(isf, osf, t1SocketHint, t2SocketHint, t3SocketHint, rSocketHint, performer);
}

public Supplier<Operation> createAllMatTwoSource(
SocketHint<Mat> matSocketHint,
SocketHint<Mat> matSocketHint2,
Expand Down
Original file line number Diff line number Diff line change
@@ -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<T1, T2, T3, R> implements Operation {
private final InputSocket<T1> input1;
private final InputSocket<T2> input2;
private final InputSocket<T3> input3;
private final OutputSocket<R> output;
private final Performer<T1, T2, T3, R> performer;

@FunctionalInterface
public interface Performer<T1, T2, T3, R> {
R perform(T1 src1, T2 src2, T3 src3);
}

ThreeSourceReturnDestinationOperation(
InputSocket.Factory inputSocketFactory,
OutputSocket.Factory outputSocketFactory,
SocketHint<T1> t1SocketHint,
SocketHint<T2> t2SocketHint,
SocketHint<T3> t3SocketHint,
SocketHint<R> rSocketHint,
Performer<T1, T2, T3, R> 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<InputSocket> getInputSockets() {
return ImmutableList.of(input1, input2, input3);
}

@Override
public List<OutputSocket> getOutputSockets() {
return ImmutableList.of(output);
}

@Override
@SuppressWarnings("OptionalGetWithoutIsPresent")
public void perform() {
output.setValue(performer.perform(
input1.getValue().get(),
input2.getValue().get(),
input3.getValue().get()));
}
}