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