blob: c664391981a071b0a296ef312679c5cc5e97deb9 [file] [log] [blame]
jerrymcb7a06a2013-02-17 22:32:29 +00001package org.frc971;
2
jerrymcd2c3322013-02-18 08:49:01 +00003import java.awt.BorderLayout;
4import java.awt.GridLayout;
jerrymcb7a06a2013-02-17 22:32:29 +00005import java.awt.event.KeyEvent;
danielp4a35a7a2013-02-20 20:45:39 +00006import java.util.Arrays;
jerrymcb7a06a2013-02-17 22:32:29 +00007
jerrymcd2c3322013-02-18 08:49:01 +00008import javax.swing.JPanel;
9import javax.swing.JSlider;
jerrymcb7a06a2013-02-17 22:32:29 +000010import javax.swing.WindowConstants;
jerrymcd2c3322013-02-18 08:49:01 +000011import javax.swing.event.ChangeEvent;
12import javax.swing.event.ChangeListener;
jerrymcb7a06a2013-02-17 22:32:29 +000013
14import com.googlecode.javacv.CanvasFrame;
jerrymcb7a06a2013-02-17 22:32:29 +000015import edu.wpi.first.wpijavacv.WPIColorImage;
jerrym6ebe6452013-02-18 03:00:31 +000016import edu.wpi.first.wpijavacv.WPIImage;
jerrymcb7a06a2013-02-17 22:32:29 +000017
18/* REQUIRED JAVA LIBRARIES:
jerrym38d8af12013-02-18 06:54:13 +000019 * external_jars/
20 * javacpp.jar
21 * javacv-YOUR_OS.jar
22 * javacv.jar
23 * WPIJavaCV.jar
jerrymcb7a06a2013-02-17 22:32:29 +000024 *
jerrym38d8af12013-02-18 06:54:13 +000025 * REQUIRED NATIVE CODE LIBRARIES ON $PATH:
26 * Program Files/WPIJavaCV/ [for example]
jerrymcb7a06a2013-02-17 22:32:29 +000027 * JavaCV_2.2.0/javacv-bin/javacv-YOUR_OS.jar
28 * OpenCV_2.2.0/bin/*
jerrym38d8af12013-02-18 06:54:13 +000029 *
30 * The native libraries and javacv-YOUR_OS.jar must match the 32 vs. 64-bit JVM.
jerrymcb7a06a2013-02-17 22:32:29 +000031 */
32/**
33 * FRC 2013 vision-target recognizer tuner app.
34 *
jerrymf96c32c2013-02-18 19:30:45 +000035 * <p>
36 * See {@link #processEvents()} for the keystroke commands.
37 *
jerrymcb7a06a2013-02-17 22:32:29 +000038 * @author jerry
danielp4a35a7a2013-02-20 20:45:39 +000039 * @author daniel
jerrymcb7a06a2013-02-17 22:32:29 +000040 */
41public class VisionTuner {
jerrym6ebe6452013-02-18 03:00:31 +000042 private Recognizer recognizer = new Recognizer2013();
jerrymcb7a06a2013-02-17 22:32:29 +000043
jerrymcd2c3322013-02-18 08:49:01 +000044 private final CanvasFrame cameraFrame = new CanvasFrame("Camera");
45 private final JPanel panel = new JPanel();
46 private final JSlider hueMinSlider = new JSlider();
47 private final JSlider hueMaxSlider = new JSlider();
48 private final JSlider satMinSlider = new JSlider();
49 private final JSlider valMinSlider = new JSlider();
50
jerrymf0c84552013-02-19 00:51:20 +000051 private int totalFrames = -1; // don't count the first (warmup) frame
jerrymf96c32c2013-02-18 19:30:45 +000052 private double totalMsec;
53 private double minMsec = Double.MAX_VALUE;
54 private double maxMsec;
danielp4a35a7a2013-02-20 20:45:39 +000055
56 private TestImageGetter getter;
jerryma1cd68d2013-02-18 09:16:19 +000057
danielp4a35a7a2013-02-20 20:45:39 +000058 public VisionTuner() {
jerrymcb7a06a2013-02-17 22:32:29 +000059 cameraFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jerrymcb7a06a2013-02-17 22:32:29 +000060
jerrymf96c32c2013-02-18 19:30:45 +000061 recognizer.showIntermediateStages(true);
jerrymcd2c3322013-02-18 08:49:01 +000062
63 cameraFrame.getContentPane().add(panel, BorderLayout.SOUTH);
64 panel.setLayout(new GridLayout(0, 2, 0, 0));
65
66 ChangeListener sliderListener = new ChangeListener() {
67 @Override
jerrymdda60132013-02-18 09:25:03 +000068 public void stateChanged(ChangeEvent e) {
69 System.out.println("New HSV range ["
70 + hueMinSlider.getValue() + " .. "
jerrymcd2469c2013-02-18 20:15:28 +000071 + hueMaxSlider.getValue() + "] "
72 + satMinSlider.getValue() + "+ "
73 + valMinSlider.getValue() + "+");
jerrymdda60132013-02-18 09:25:03 +000074 recognizer.setHSVRange(
75 hueMinSlider.getValue(), hueMaxSlider.getValue(),
76 satMinSlider.getValue(),
77 valMinSlider.getValue());
danielp4a35a7a2013-02-20 20:45:39 +000078 processImage(getter.GetCurrent());
jerrymcd2c3322013-02-18 08:49:01 +000079 }
80 };
81
jerrymcd2c3322013-02-18 08:49:01 +000082 hueMinSlider.setToolTipText("minimum HSV hue");
83 hueMinSlider.setMaximum(255);
jerrymcd2469c2013-02-18 20:15:28 +000084 hueMinSlider.setValue(recognizer.getHueMin());
jerrymcd2c3322013-02-18 08:49:01 +000085 panel.add(hueMinSlider);
86
jerrymcd2c3322013-02-18 08:49:01 +000087 hueMaxSlider.setToolTipText("maximum HSV hue");
88 hueMaxSlider.setMaximum(255);
jerrymcd2469c2013-02-18 20:15:28 +000089 hueMaxSlider.setValue(recognizer.getHueMax());
jerrymcd2c3322013-02-18 08:49:01 +000090 panel.add(hueMaxSlider);
91
jerrymcd2c3322013-02-18 08:49:01 +000092 satMinSlider.setToolTipText("minimum HSV color saturation");
93 satMinSlider.setMaximum(255);
jerrymcd2469c2013-02-18 20:15:28 +000094 satMinSlider.setValue(recognizer.getSatMin());
jerrymcd2c3322013-02-18 08:49:01 +000095 panel.add(satMinSlider);
96
jerrymcd2c3322013-02-18 08:49:01 +000097 valMinSlider.setToolTipText("minimum HSV brightness value");
98 valMinSlider.setMaximum(255);
jerrymcd2469c2013-02-18 20:15:28 +000099 valMinSlider.setValue(recognizer.getValMin());
jerrymcd2c3322013-02-18 08:49:01 +0000100 panel.add(valMinSlider);
101
jerrymcd2469c2013-02-18 20:15:28 +0000102 System.out.println("Initial HSV range ["
103 + hueMinSlider.getValue() + " .. "
104 + hueMaxSlider.getValue() + "] "
105 + satMinSlider.getValue() + "+ "
106 + valMinSlider.getValue() + "+");
107
jerrymcd2c3322013-02-18 08:49:01 +0000108 hueMinSlider.addChangeListener(sliderListener);
109 hueMaxSlider.addChangeListener(sliderListener);
110 satMinSlider.addChangeListener(sliderListener);
111 valMinSlider.addChangeListener(sliderListener);
jerrymcb7a06a2013-02-17 22:32:29 +0000112 }
113
jerrymcb7a06a2013-02-17 22:32:29 +0000114 /**
115 * Loads the named test image files.
116 * Sets testImageFilenames and testImages.
117 */
jerrymcb7a06a2013-02-17 22:32:29 +0000118
danielp4a35a7a2013-02-20 20:45:39 +0000119 private void processImage(WPIColorImage cameraImage) {
120 cameraFrame.setTitle("Test Images:");
jerrym6ebe6452013-02-18 03:00:31 +0000121
jerryma1cd68d2013-02-18 09:16:19 +0000122 long startTime = System.nanoTime();
jerrym6ebe6452013-02-18 03:00:31 +0000123 WPIImage processedImage = recognizer.processImage(cameraImage);
jerryma1cd68d2013-02-18 09:16:19 +0000124 long endTime = System.nanoTime();
125
jerrym6ebe6452013-02-18 03:00:31 +0000126 cameraFrame.showImage(processedImage.getBufferedImage());
jerryma1cd68d2013-02-18 09:16:19 +0000127
128 double milliseconds = (endTime - startTime) / 1e6;
jerrymf0c84552013-02-19 00:51:20 +0000129 if (++totalFrames > 0) {
130 totalMsec += milliseconds;
131 minMsec = Math.min(minMsec, milliseconds);
132 maxMsec = Math.max(maxMsec, milliseconds);
133 System.out.format("The recognizer took %.2f ms, %.2f fps, %.2f avg%n",
134 milliseconds, 1000 / milliseconds,
135 1000 * totalFrames / totalMsec);
136 }
jerrymcb7a06a2013-02-17 22:32:29 +0000137 }
138
139 private void previousImage() {
danielp4a35a7a2013-02-20 20:45:39 +0000140 WPIColorImage to_process = getter.GetPrev();
141 if (to_process != null)
142 processImage(to_process);
jerrymcb7a06a2013-02-17 22:32:29 +0000143 }
144
145 private void nextImage() {
danielp4a35a7a2013-02-20 20:45:39 +0000146 WPIColorImage to_process = getter.GetNext();
147 if (to_process != null)
148 processImage(to_process);
jerrymcb7a06a2013-02-17 22:32:29 +0000149 }
150
151 private void processEvents() {
jerrymdda60132013-02-18 09:25:03 +0000152 KeyEvent e = cameraFrame.waitKey();
jerrymcb7a06a2013-02-17 22:32:29 +0000153
jerrymdda60132013-02-18 09:25:03 +0000154 switch (e.getKeyCode()) {
jerrymf96c32c2013-02-18 19:30:45 +0000155 case KeyEvent.VK_LEFT: // left arrow key: go to previous image
jerrymdda60132013-02-18 09:25:03 +0000156 previousImage();
157 break;
jerrymf96c32c2013-02-18 19:30:45 +0000158 case KeyEvent.VK_RIGHT: // right arrow key: go to next image
jerrymdda60132013-02-18 09:25:03 +0000159 nextImage();
160 break;
jerrymf96c32c2013-02-18 19:30:45 +0000161 case KeyEvent.VK_Q: // Q: print time measurements then quit
162 System.out.format("The recognizer took %.2f ms avg, %.2f min,"
163 + " %.2f max, %.2f fps avg%n",
164 totalMsec / totalFrames,
165 minMsec, maxMsec,
166 1000 * totalFrames / totalMsec);
167 System.exit(0);
jerrymdda60132013-02-18 09:25:03 +0000168 }
jerrymcb7a06a2013-02-17 22:32:29 +0000169 }
170
171 public static void main(final String[] args) {
danielp4a35a7a2013-02-20 20:45:39 +0000172 VisionTuner tuner = new VisionTuner();
173 if (Arrays.asList(args).contains("-debug")) {
174 //debug mode has been requested
175 tuner.getter = new TestImageGetter(".");
176 WPIColorImage to_process = tuner.getter.GetNext();
177 if (to_process != null)
178 tuner.processImage(to_process);
179 else
180 System.err.println("Cannot find test images.");
181 for (;;) {
182 tuner.processEvents();
183 }
jerrymcb7a06a2013-02-17 22:32:29 +0000184 }
danielp4a35a7a2013-02-20 20:45:39 +0000185 else {
186 HTTPClient client = new HTTPClient();
187 for (;;) {
188 ImageWithTimestamp to_process = client.GetFrame();
189 if (to_process.image != null) {
190 tuner.processImage(to_process.image);
191 System.out.println("Captured time: " + Double.toString(to_process.timestamp));
192 }
193 }
jerrymcb7a06a2013-02-17 22:32:29 +0000194 }
195 }
196
197}