Wednesday, February 14, 2018
Using the leJOS 0 9 video library
Using the leJOS 0 9 video library
The following program illustrates how one might use the LeJOS-0.9 webcam library in conjunction with the lambda feature from Java 8:
package edu.hendrix.demo;
import java.io.IOException;
import java.util.function.Consumer;
import lejos.hardware.BrickFinder;
import lejos.hardware.Button;
import lejos.hardware.lcd.GraphicsLCD;
import lejos.hardware.video.Video;
import lejos.hardware.video.YUYVImage;
public class FilteredCameraDemo {
private Consumer<YUYVimage> imgConsumer;
public FilteredCameraDemo(Consumer<YUYVimage> filterer) {
imgConsumer = filterer;
}
public void run() {
try {
Video wc = BrickFinder.getDefault().getVideo();
wc.open(160,120);
byte[] frame = wc.createFrame();
YUYVImage img =
new YUYVImage(frame, wc.getWidth(), wc.getHeight());
while (!Button.ESCAPE.isDown()) {
wc.grabFrame(frame);
imgConsumer.accept(img);
}
wc.close();
} catch (IOException ioe) {
ioe.printStackTrace();
System.out.println("Driver exception: " + ioe.getMessage());
}
}
public static void main(String[] args) {
GraphicsLCD g = BrickFinder.getDefault().getGraphicsLCD();
new FilteredCameraDemo
(img -> img.display(g, 0, 0, img.getMeanY())).run();
}
}
To allow flexibility of implementation, the
YUYVImage
class is essentially a wrapper around a byte array. So every time we grab a frame from the webcam, we dump the bytes into a byte array that, in turn, we access via a YUYVImage
that maintains a reference to it. This YUYVImage
class has methods that decode the byte layout according to the YUYV standard. We have a private data member belonging to the
Consumer
interface. Consumer
objects have an accept()
method that takes a parameter (corresponding to the parameterized type) and does not return anything. We make use of this within the run()
methods while loop. In this case, the type parameter is a YUYVImage
object. Now, when we invoke the constructor, we can write a lambda expression to describe the desired computation. For this example, we just display the image. Note that the LCD screen is referenced from outside the scope of the lambda. This still works after it has gone out of scope, as Java 8s lambda expressions are closures. You can write code to do arbitrary things when seeing an image, just by calling the
FilteredCameraDemo
constructor with a different lambda parameter.I plan to write a more elaborate example in a future blog post, but this should suffice to demonstrate the concept. Happy coding!