Monday, August 4, 2014

Webcam with Lego Mindstorms EV3, part 3 (Java Demo)

Having rebuilt the kernel to include the Video4Linux2 drivers, and having written a JNI driver, we are now ready to write a Java program that demonstrates the webcam in action.  We will create two classes to do this.  The first class will represent the YUYV format image that was acquired.  This class is designed to provide a layer of abstraction above the byte array returned by the grabFrame() method in Webcam.java.  It also provides a display() method that will write a value to each corresponding pixel on the LCD display.  Since the LCD is a monochrome display, we select the pixel display value based on whether the image pixel Y value is above or below the mean Y value across the image.


 import java.io.IOException;  
   
 import lejos.hardware.lcd.LCD;  
   
 public class YUYVImage {  
     private byte[] pix;  
     private int width, height;  
       
     YUYVImage(byte[] pix, int width, int height) {  
         this.pix = pix;  
         this.width = width;  
         this.height = height;  
     }  
       
     public static YUYVImage grab() throws IOException {  
         return new YUYVImage(Webcam.grabFrame(), Webcam.getWidth(), Webcam.getHeight());  
     }  
       
     public int getNumPixels() {return pix.length / 2;}  
       
     public int getWidth() {return width;}  
       
     public int getHeight() {return height;}  
       
     public int getY(int x, int y) {
         return getValueAt(2 * (y * width + x));
     }
 
     public int getU(int x, int y) {
         return getValueAt(getPairBase(x, y) + 1);
     }
 
     public int getV(int x, int y) {
         return getValueAt(getPairBase(x, y) + 3);
     }
 
     private int getValueAt(int index) {
         return pix[index] & 0xFF;
     }
       
     private int getPairBase(int x, int y) {  
         return 2 * (y * width + (x - x % 2));  
     }  
       
     public int getMeanY() {  
         int total = 0;  
         for (int i = 0; i < pix.length; i += 2) {  
             total += pix[i];  
         }  
         return total / getNumPixels();  
     }  
       
     public void display() {  
         int mean = getMeanY();  
         for (int i = 0; i < pix.length; i += 2) {  
             int x = (i / 2) % width;  
             int y = (i / 2) / width;  
             LCD.setPixel(x, y, pix[i] > mean ? 1 : 0);  
         }  
     }  
 }  
   
Having created a representation, we can now create a main loop that sets up the camera, grabs and displays the images, and shuts down the camera when finished.


 import java.io.IOException;  
   
 import lejos.hardware.Button;  
 import lejos.hardware.lcd.LCD;  
   
 public class CameraDemo {  
     public static void main(String[] args) {  
         try {  
             Webcam.start();  
             while (!Button.ESCAPE.isDown()) {  
                 YUYVImage img = YUYVImage.grab();  
                 img.display();  
             }  
   
             double fps = Webcam.end();  
             LCD.clear();  
             System.out.println(fps + " fps");  
             while (!Button.ESCAPE.isDown());  
         } catch (IOException ioe) {  
             ioe.printStackTrace();  
             System.out.println("Driver exception: " + ioe.getMessage());  
         }  
     }  
 }  
   
Once all of this code is entered and compiled, you should be ready to go.  Here's a video I recorded of CameraDemo in action.

No comments:

Post a Comment