Skip to content

Commit ef0ffd3

Browse files
committed
[apriltag] Make AprilTagDetector.detect() use RawFrame instead of OpenCV Mat
1 parent 72fdca3 commit ef0ffd3

File tree

4 files changed

+62
-35
lines changed

4 files changed

+62
-35
lines changed

apriltag/src/main/java/edu/wpi/first/apriltag/AprilTagDetector.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
package edu.wpi.first.apriltag;
66

77
import edu.wpi.first.apriltag.jni.AprilTagJNI;
8-
import org.opencv.core.Mat;
8+
import edu.wpi.first.util.RawFrame;
99

1010
/**
1111
* An AprilTag detector engine. This is expensive to set up and tear down, so most use cases should
@@ -293,11 +293,12 @@ public void clearFamilies() {
293293
*
294294
* <p>The image must be grayscale.
295295
*
296-
* @param img 8-bit OpenCV Mat image
296+
* @param frame The frame object containing an 8-bit image.
297297
* @return Results (array of AprilTagDetection)
298298
*/
299-
public AprilTagDetection[] detect(Mat img) {
300-
return AprilTagJNI.detect(m_native, img.cols(), img.rows(), (int) img.step1(), img.dataAddr());
299+
public AprilTagDetection[] detect(RawFrame frame) {
300+
return AprilTagJNI.detect(
301+
m_native, frame.getWidth(), frame.getHeight(), frame.getWidth(), frame.getDataPtr());
301302
}
302303

303304
private long m_native;

apriltag/src/test/java/edu/wpi/first/apriltag/AprilTagDetectorTest.java

+32-30
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
import edu.wpi.first.math.geometry.Transform3d;
1212
import edu.wpi.first.math.util.Units;
13+
import edu.wpi.first.util.PixelFormat;
14+
import edu.wpi.first.util.RawFrame;
1315
import edu.wpi.first.util.RuntimeLoader;
1416
import java.io.ByteArrayOutputStream;
1517
import java.io.IOException;
@@ -132,7 +134,7 @@ public Mat loadImage(String resource) throws IOException {
132134
}
133135

134136
@Test
135-
void testDecodeCropped() {
137+
void testDecodeAndPose() {
136138
detector.addFamily("tag16h5");
137139
detector.addFamily("tag36h11");
138140

@@ -144,35 +146,14 @@ void testDecodeCropped() {
144146
return;
145147
}
146148

147-
// Pre-knowledge -- the tag is within this ROI of this particular test image
148-
var cropped = image.submat(100, 400, 220, 570);
149-
150-
try {
151-
AprilTagDetection[] results = detector.detect(cropped);
152-
assertEquals(1, results.length);
153-
assertEquals("tag36h11", results[0].getFamily());
154-
assertEquals(1, results[0].getId());
155-
assertEquals(0, results[0].getHamming());
156-
} finally {
157-
cropped.release();
158-
image.release();
159-
}
160-
}
149+
var frameBytes = new byte[image.width() * image.height()];
150+
image.get(0, 0, frameBytes);
161151

162-
@Test
163-
void testDecodeAndPose() {
164-
detector.addFamily("tag16h5");
165-
detector.addFamily("tag36h11");
152+
var frame = new RawFrame();
153+
frame.setData(frameBytes, image.width(), image.height(), 1, PixelFormat.kGray);
166154

167-
Mat image;
168155
try {
169-
image = loadImage("tag1_640_480.jpg");
170-
} catch (IOException ex) {
171-
fail(ex);
172-
return;
173-
}
174-
try {
175-
AprilTagDetection[] results = detector.detect(image);
156+
AprilTagDetection[] results = detector.detect(frame);
176157
assertEquals(1, results.length);
177158
assertEquals("tag36h11", results[0].getFamily());
178159
assertEquals(1, results[0].getId());
@@ -204,8 +185,15 @@ void testPoseRotatedX() {
204185
fail(ex);
205186
return;
206187
}
188+
189+
var frameBytes = new byte[image.width() * image.height()];
190+
image.get(0, 0, frameBytes);
191+
192+
var frame = new RawFrame();
193+
frame.setData(frameBytes, image.width(), image.height(), 1, PixelFormat.kGray);
194+
207195
try {
208-
AprilTagDetection[] results = detector.detect(image);
196+
AprilTagDetection[] results = detector.detect(frame);
209197
assertEquals(1, results.length);
210198

211199
var estimator =
@@ -237,8 +225,15 @@ void testPoseRotatedY() {
237225
fail(ex);
238226
return;
239227
}
228+
229+
var frameBytes = new byte[image.width() * image.height()];
230+
image.get(0, 0, frameBytes);
231+
232+
var frame = new RawFrame();
233+
frame.setData(frameBytes, image.width(), image.height(), 1, PixelFormat.kGray);
234+
240235
try {
241-
AprilTagDetection[] results = detector.detect(image);
236+
AprilTagDetection[] results = detector.detect(frame);
242237
assertEquals(1, results.length);
243238

244239
var estimator =
@@ -267,8 +262,15 @@ void testPoseStraightOn() {
267262
fail(ex);
268263
return;
269264
}
265+
266+
var frameBytes = new byte[image.width() * image.height()];
267+
image.get(0, 0, frameBytes);
268+
269+
var frame = new RawFrame();
270+
frame.setData(frameBytes, image.width(), image.height(), 1, PixelFormat.kGray);
271+
270272
try {
271-
AprilTagDetection[] results = detector.detect(image);
273+
AprilTagDetection[] results = detector.detect(frame);
272274
assertEquals(1, results.length);
273275

274276
var estimator =

wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/apriltagsvision/Robot.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import edu.wpi.first.networktables.IntegerArrayPublisher;
1717
import edu.wpi.first.networktables.NetworkTable;
1818
import edu.wpi.first.networktables.NetworkTableInstance;
19+
import edu.wpi.first.util.PixelFormat;
20+
import edu.wpi.first.util.RawFrame;
1921
import edu.wpi.first.wpilibj.TimedRobot;
2022
import java.util.ArrayList;
2123
import org.opencv.core.Mat;
@@ -65,6 +67,9 @@ void apriltagVisionThreadProc() {
6567
var mat = new Mat();
6668
var grayMat = new Mat();
6769

70+
var frameBytes = new byte[640 * 480];
71+
var frame = new RawFrame();
72+
6873
// Instantiate once
6974
ArrayList<Long> tags = new ArrayList<>();
7075
var outlineColor = new Scalar(0, 255, 0);
@@ -89,7 +94,10 @@ void apriltagVisionThreadProc() {
8994

9095
Imgproc.cvtColor(mat, grayMat, Imgproc.COLOR_RGB2GRAY);
9196

92-
AprilTagDetection[] detections = detector.detect(grayMat);
97+
grayMat.get(0, 0, frameBytes);
98+
frame.setData(frameBytes, grayMat.width(), grayMat.height(), 1, PixelFormat.kGray);
99+
100+
AprilTagDetection[] detections = detector.detect(frame);
93101

94102
// have not seen any tags yet
95103
tags.clear();

wpiutil/src/main/java/edu/wpi/first/util/RawFrame.java

+16
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,22 @@ public void setData(ByteBuffer data, int width, int height, int stride, PixelFor
8888
m_nativeObj, data, data.limit(), width, height, stride, pixelFormat.getValue());
8989
}
9090

91+
/**
92+
* Set frame data.
93+
*
94+
* @param data A byte array containing the frame data.
95+
* @param width The width of the frame, in pixels
96+
* @param height The height of the frame, in pixels
97+
* @param stride The number of bytes in each row of image data
98+
* @param pixelFormat The PixelFormat of the frame
99+
*/
100+
public void setData(byte[] data, int width, int height, int stride, PixelFormat pixelFormat) {
101+
var dataByteBuffer = ByteBuffer.allocateDirect(width * height * stride);
102+
dataByteBuffer.put(data);
103+
104+
setData(dataByteBuffer, width, height, stride, pixelFormat);
105+
}
106+
91107
/**
92108
* Call to set frame information.
93109
*

0 commit comments

Comments
 (0)