Skip to content

Commit c2b0a9f

Browse files
committed
Adds Number Threshold, Count Contours, and Crop Operations
Rewrite of @MeRPG's PR. Closes #529
1 parent a6d6c07 commit c2b0a9f

File tree

4 files changed

+177
-0
lines changed

4 files changed

+177
-0
lines changed

core/src/main/java/edu/wpi/grip/core/operations/Operations.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.google.inject.Inject;
77
import com.google.inject.Singleton;
88
import com.google.inject.name.Named;
9+
import edu.wpi.grip.core.OperationDescription;
910
import edu.wpi.grip.core.OperationMetaData;
1011
import edu.wpi.grip.core.events.OperationAddedEvent;
1112
import edu.wpi.grip.core.operations.composite.*;
@@ -21,9 +22,15 @@
2122
import edu.wpi.grip.core.operations.opencv.MinMaxLoc;
2223
import edu.wpi.grip.core.operations.opencv.NewPointOperation;
2324
import edu.wpi.grip.core.operations.opencv.NewSizeOperation;
25+
import edu.wpi.grip.core.operations.templated.TemplateFactory;
2426
import edu.wpi.grip.core.sockets.InputSocket;
2527
import edu.wpi.grip.core.sockets.OutputSocket;
28+
import edu.wpi.grip.core.sockets.SocketHint;
29+
import edu.wpi.grip.core.sockets.SocketHints;
30+
import edu.wpi.grip.core.util.Icon;
31+
import org.bytedeco.javacpp.opencv_core.Mat;
2632
import org.bytedeco.javacpp.opencv_core.Point;
33+
import org.bytedeco.javacpp.opencv_core.Rect;
2734
import org.bytedeco.javacpp.opencv_core.Size;
2835

2936
import static com.google.common.base.Preconditions.checkNotNull;
@@ -44,6 +51,8 @@ public class Operations {
4451
this.eventBus = checkNotNull(eventBus, "EventBus cannot be null");
4552
checkNotNull(ntPublisherFactory, "ntPublisherFactory cannot be null");
4653
checkNotNull(rosPublishFactory, "rosPublishFactory cannot be null");
54+
TemplateFactory templateFactory = new TemplateFactory(isf, osf);
55+
4756
this.operations = ImmutableList.of(
4857
// Composite operations
4958
new OperationMetaData(BlurOperation.DESCRIPTION, () -> new BlurOperation(isf, osf)),
@@ -67,6 +76,52 @@ public class Operations {
6776
new OperationMetaData(WatershedOperation.DESCRIPTION, () -> new WatershedOperation(isf, osf)),
6877
new OperationMetaData(ThresholdMoving.DESCRIPTION, () -> new ThresholdMoving(isf, osf)),
6978

79+
new OperationMetaData(
80+
OperationDescription.builder()
81+
.name("Crop")
82+
.summary("Crop an image")
83+
.icon(Icon.iconStream("grip"))
84+
.build(),
85+
templateFactory.create(
86+
SocketHints.Inputs.createMatSocketHint("src", false),
87+
SocketHints.Inputs.createPointSocketHint("p1", false),
88+
SocketHints.Inputs.createPointSocketHint("p2", false),
89+
SocketHints.Inputs.createMatSocketHint("dst", true),
90+
(src, p1, p2, dst) -> {
91+
final Rect rect = new Rect(p1, p2);
92+
final Mat tmp = new Mat(src, rect);
93+
tmp.copyTo(dst);
94+
}
95+
)),
96+
97+
new OperationMetaData(
98+
OperationDescription.builder()
99+
.name("Number Threshold")
100+
.summary("Returns a boolean on whether or not the number is within the given range.")
101+
.icon(Icon.iconStream("grip"))
102+
.build(),
103+
templateFactory.createReturning(
104+
SocketHints.Inputs.createNumberSpinnerSocketHint("Input", 0),
105+
SocketHints.Inputs.createNumberSpinnerSocketHint("Min", -1),
106+
SocketHints.Inputs.createNumberSpinnerSocketHint("Max", 1),
107+
SocketHints.Outputs.createBooleanSocketHint("Output", true),
108+
(num, min, max) -> min.doubleValue() <= num.doubleValue() && max.doubleValue() >= num.doubleValue()
109+
)
110+
),
111+
112+
new OperationMetaData(
113+
OperationDescription.builder()
114+
.name("Count Contours")
115+
.summary("Counts the number of contours in a contours report.")
116+
.icon(Icon.iconStream("grip"))
117+
.build(),
118+
templateFactory.createReturning(
119+
new SocketHint.Builder<>(ContoursReport.class).identifier("Contours").build(),
120+
SocketHints.Outputs.createNumberSocketHint("Count", 0),
121+
(contours) -> contours.getContours().size()
122+
)
123+
),
124+
70125
// OpenCV operations
71126
new OperationMetaData(MatFieldAccessor.DESCRIPTION, () -> new MatFieldAccessor(isf, osf)),
72127
new OperationMetaData(MinMaxLoc.DESCRIPTION, () -> new MinMaxLoc(isf, osf)),
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package edu.wpi.grip.core.operations.templated;
2+
3+
4+
import com.google.common.collect.ImmutableList;
5+
import edu.wpi.grip.core.Operation;
6+
import edu.wpi.grip.core.sockets.InputSocket;
7+
import edu.wpi.grip.core.sockets.OutputSocket;
8+
import edu.wpi.grip.core.sockets.SocketHint;
9+
10+
import java.util.List;
11+
12+
class OneSourceReturnDestinationOperation<T1, R> implements Operation {
13+
private final InputSocket<T1> input1;
14+
private final OutputSocket<R> output;
15+
private final Performer<T1, R> performer;
16+
17+
@FunctionalInterface
18+
public interface Performer<T1, R> {
19+
R perform(T1 src1);
20+
}
21+
22+
OneSourceReturnDestinationOperation(InputSocket.Factory inputSocketFactory,
23+
OutputSocket.Factory outputSocketFactory,
24+
SocketHint<T1> t1SocketHint,
25+
SocketHint<R> rSocketHint,
26+
Performer<T1, R> performer) {
27+
this.input1 = inputSocketFactory.create(t1SocketHint);
28+
this.output = outputSocketFactory.create(rSocketHint);
29+
assert output.getValue().isPresent() : TemplateFactory.ASSERTION_MESSAGE;
30+
this.performer = performer;
31+
}
32+
33+
@Override
34+
public List<InputSocket> getInputSockets() {
35+
return ImmutableList.of(input1);
36+
}
37+
38+
@Override
39+
public List<OutputSocket> getOutputSockets() {
40+
return ImmutableList.of(output);
41+
}
42+
43+
@Override
44+
@SuppressWarnings("OptionalGetWithoutIsPresent")
45+
public void perform() {
46+
output.setValue(performer.perform(input1.getValue().get()));
47+
}
48+
}

core/src/main/java/edu/wpi/grip/core/operations/templated/TemplateFactory.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@ public <T1, T2, T3, T4, T5, T6, T7, R> Supplier<Operation> create(
101101
return () -> new SevenSourceOneDestinationOperation<>(isf, osf, t1SocketHint, t2SocketHint, t3SocketHint, t4SocketHint, t5SocketHint, t6SocketHint, t7SocketHint, rSocketHint, performer);
102102
}
103103

104+
public <T1, R> Supplier<Operation> createReturning(
105+
SocketHint<T1> t1SocketHint,
106+
SocketHint<R> rSocketHint,
107+
OneSourceReturnDestinationOperation.Performer<T1, R> performer) {
108+
return () -> new OneSourceReturnDestinationOperation<>(isf, osf, t1SocketHint, rSocketHint, performer);
109+
}
110+
111+
public <T1, T2, T3, R> Supplier<Operation> createReturning(
112+
SocketHint<T1> t1SocketHint,
113+
SocketHint<T2> t2SocketHint,
114+
SocketHint<T3> t3SocketHint,
115+
SocketHint<R> rSocketHint,
116+
ThreeSourceReturnDestinationOperation.Performer<T1, T2, T3, R> performer) {
117+
return () -> new ThreeSourceReturnDestinationOperation<>(isf, osf, t1SocketHint, t2SocketHint, t3SocketHint, rSocketHint, performer);
118+
}
119+
104120
public Supplier<Operation> createAllMatTwoSource(
105121
SocketHint<Mat> matSocketHint,
106122
SocketHint<Mat> matSocketHint2,
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package edu.wpi.grip.core.operations.templated;
2+
3+
4+
import com.google.common.collect.ImmutableList;
5+
import edu.wpi.grip.core.Operation;
6+
import edu.wpi.grip.core.sockets.InputSocket;
7+
import edu.wpi.grip.core.sockets.OutputSocket;
8+
import edu.wpi.grip.core.sockets.SocketHint;
9+
10+
import java.util.List;
11+
12+
class ThreeSourceReturnDestinationOperation<T1, T2, T3, R> implements Operation {
13+
private final InputSocket<T1> input1;
14+
private final InputSocket<T2> input2;
15+
private final InputSocket<T3> input3;
16+
private final OutputSocket<R> output;
17+
private final Performer<T1, T2, T3, R> performer;
18+
19+
@FunctionalInterface
20+
public interface Performer<T1, T2, T3, R> {
21+
R perform(T1 src1, T2 src2, T3 src3);
22+
}
23+
24+
ThreeSourceReturnDestinationOperation(
25+
InputSocket.Factory inputSocketFactory,
26+
OutputSocket.Factory outputSocketFactory,
27+
SocketHint<T1> t1SocketHint,
28+
SocketHint<T2> t2SocketHint,
29+
SocketHint<T3> t3SocketHint,
30+
SocketHint<R> rSocketHint,
31+
Performer<T1, T2, T3, R> performer) {
32+
this.performer = performer;
33+
this.input1 = inputSocketFactory.create(t1SocketHint);
34+
this.input2 = inputSocketFactory.create(t2SocketHint);
35+
this.input3 = inputSocketFactory.create(t3SocketHint);
36+
this.output = outputSocketFactory.create(rSocketHint);
37+
assert output.getValue().isPresent() : TemplateFactory.ASSERTION_MESSAGE;
38+
}
39+
40+
@Override
41+
public List<InputSocket> getInputSockets() {
42+
return ImmutableList.of(input1, input2, input3);
43+
}
44+
45+
@Override
46+
public List<OutputSocket> getOutputSockets() {
47+
return ImmutableList.of(output);
48+
}
49+
50+
@Override
51+
@SuppressWarnings("OptionalGetWithoutIsPresent")
52+
public void perform() {
53+
output.setValue(performer.perform(
54+
input1.getValue().get(),
55+
input2.getValue().get(),
56+
input3.getValue().get()));
57+
}
58+
}

0 commit comments

Comments
 (0)