5
5
import edu .wpi .grip .core .operations .network .Publishable ;
6
6
import edu .wpi .grip .core .sockets .NoSocketTypeLabel ;
7
7
import edu .wpi .grip .core .sockets .Socket ;
8
+ import edu .wpi .grip .core .util .LazyInit ;
9
+ import edu .wpi .grip .core .util .PointerStream ;
8
10
9
11
import com .google .auto .value .AutoValue ;
10
12
13
+ import org .bytedeco .javacpp .opencv_core .RotatedRect ;
14
+ import org .bytedeco .javacpp .opencv_imgproc ;
15
+
11
16
import java .util .ArrayList ;
12
17
import java .util .List ;
13
- import java .util .Optional ;
18
+ import java .util .stream . Stream ;
14
19
15
20
import static org .bytedeco .javacpp .opencv_core .Mat ;
16
21
import static org .bytedeco .javacpp .opencv_core .MatVector ;
17
22
import static org .bytedeco .javacpp .opencv_core .Rect ;
18
- import static org .bytedeco .javacpp .opencv_imgproc .boundingRect ;
19
23
import static org .bytedeco .javacpp .opencv_imgproc .contourArea ;
20
24
import static org .bytedeco .javacpp .opencv_imgproc .convexHull ;
21
25
@@ -31,7 +35,9 @@ public final class ContoursReport implements Publishable {
31
35
private final int rows ;
32
36
private final int cols ;
33
37
private final MatVector contours ;
34
- private Optional <Rect []> boundingBoxes = Optional .empty ();
38
+ private final LazyInit <Rect []> boundingBoxes = new LazyInit <>(this ::computeBoundingBoxes );
39
+ private final LazyInit <RotatedRect []> rotatedBoundingBoxes =
40
+ new LazyInit <>(this ::computeMinAreaBoundingBoxes );
35
41
36
42
/**
37
43
* Construct an empty report. This is used as a default value for {@link Socket}s containing
@@ -70,9 +76,10 @@ public List<Contour> getProcessedContours() {
70
76
double [] width = getWidth ();
71
77
double [] height = getHeights ();
72
78
double [] solidity = getSolidity ();
79
+ double [] angles = getAngles ();
73
80
for (int i = 0 ; i < contours .size (); i ++) {
74
81
processedContours .add (Contour .create (area [i ], centerX [i ], centerY [i ], width [i ], height [i ],
75
- solidity [i ]));
82
+ solidity [i ], angles [ i ] ));
76
83
}
77
84
return processedContours ;
78
85
}
@@ -82,66 +89,51 @@ public List<Contour> getProcessedContours() {
82
89
* boxes are used to compute several different properties, so it's probably not a good idea to
83
90
* compute them over and over again.
84
91
*/
85
- private synchronized Rect [] computeBoundingBoxes () {
86
- if (!boundingBoxes .isPresent ()) {
87
- Rect [] bb = new Rect [(int ) contours .size ()];
88
- for (int i = 0 ; i < contours .size (); i ++) {
89
- bb [i ] = boundingRect (contours .get (i ));
90
- }
91
-
92
- boundingBoxes = Optional .of (bb );
93
- }
92
+ private Rect [] computeBoundingBoxes () {
93
+ return PointerStream .ofMatVector (contours )
94
+ .map (opencv_imgproc ::boundingRect )
95
+ .toArray (Rect []::new );
96
+ }
94
97
95
- return boundingBoxes .get ();
98
+ private RotatedRect [] computeMinAreaBoundingBoxes () {
99
+ return PointerStream .ofMatVector (contours )
100
+ .map (opencv_imgproc ::minAreaRect )
101
+ .toArray (RotatedRect []::new );
96
102
}
97
103
98
104
@ PublishValue (key = "area" , weight = 0 )
99
105
public double [] getArea () {
100
- final double [] areas = new double [(int ) contours .size ()];
101
- for (int i = 0 ; i < contours .size (); i ++) {
102
- areas [i ] = contourArea (contours .get (i ));
103
- }
104
- return areas ;
106
+ return PointerStream .ofMatVector (contours )
107
+ .mapToDouble (opencv_imgproc ::contourArea )
108
+ .toArray ();
105
109
}
106
110
107
111
@ PublishValue (key = "centerX" , weight = 1 )
108
112
public double [] getCenterX () {
109
- final double [] centers = new double [(int ) contours .size ()];
110
- final Rect [] boundingBoxes = computeBoundingBoxes ();
111
- for (int i = 0 ; i < contours .size (); i ++) {
112
- centers [i ] = boundingBoxes [i ].x () + boundingBoxes [i ].width () / 2 ;
113
- }
114
- return centers ;
113
+ return Stream .of (boundingBoxes .get ())
114
+ .mapToDouble (r -> r .x () + r .width () / 2 )
115
+ .toArray ();
115
116
}
116
117
117
118
@ PublishValue (key = "centerY" , weight = 2 )
118
119
public double [] getCenterY () {
119
- final double [] centers = new double [(int ) contours .size ()];
120
- final Rect [] boundingBoxes = computeBoundingBoxes ();
121
- for (int i = 0 ; i < contours .size (); i ++) {
122
- centers [i ] = boundingBoxes [i ].y () + boundingBoxes [i ].height () / 2 ;
123
- }
124
- return centers ;
120
+ return Stream .of (boundingBoxes .get ())
121
+ .mapToDouble (r -> r .y () + r .height () / 2 )
122
+ .toArray ();
125
123
}
126
124
127
125
@ PublishValue (key = "width" , weight = 3 )
128
126
public synchronized double [] getWidth () {
129
- final double [] widths = new double [(int ) contours .size ()];
130
- final Rect [] boundingBoxes = computeBoundingBoxes ();
131
- for (int i = 0 ; i < contours .size (); i ++) {
132
- widths [i ] = boundingBoxes [i ].width ();
133
- }
134
- return widths ;
127
+ return Stream .of (boundingBoxes .get ())
128
+ .mapToDouble (Rect ::width )
129
+ .toArray ();
135
130
}
136
131
137
132
@ PublishValue (key = "height" , weight = 4 )
138
133
public synchronized double [] getHeights () {
139
- final double [] heights = new double [(int ) contours .size ()];
140
- final Rect [] boundingBoxes = computeBoundingBoxes ();
141
- for (int i = 0 ; i < contours .size (); i ++) {
142
- heights [i ] = boundingBoxes [i ].height ();
143
- }
144
- return heights ;
134
+ return Stream .of (boundingBoxes .get ())
135
+ .mapToDouble (Rect ::height )
136
+ .toArray ();
145
137
}
146
138
147
139
@ PublishValue (key = "solidity" , weight = 5 )
@@ -156,11 +148,19 @@ public synchronized double[] getSolidity() {
156
148
return solidities ;
157
149
}
158
150
151
+ @ PublishValue (key = "angle" , weight = 6 )
152
+ public synchronized double [] getAngles () {
153
+ return Stream .of (rotatedBoundingBoxes .get ())
154
+ .mapToDouble (RotatedRect ::angle )
155
+ .toArray ();
156
+ }
157
+
159
158
@ AutoValue
160
159
public abstract static class Contour {
161
160
public static Contour create (double area , double centerX , double centerY , double width , double
162
- height , double solidity ) {
163
- return new AutoValue_ContoursReport_Contour (area , centerX , centerY , width , height , solidity );
161
+ height , double solidity , double angle ) {
162
+ return new AutoValue_ContoursReport_Contour (area , centerX , centerY , width , height , solidity ,
163
+ angle );
164
164
}
165
165
166
166
public abstract double area ();
@@ -174,5 +174,7 @@ public static Contour create(double area, double centerX, double centerY, double
174
174
public abstract double height ();
175
175
176
176
public abstract double solidity ();
177
+
178
+ public abstract double angle ();
177
179
}
178
180
}
0 commit comments