Now that we have my EV3 connected to Dropbox, let’s have some fun. In this project I use a cheap webcam connected to the EV3 to take a photo and upload it into my Dropbox account. It’s a wireless digital camera using the EV3 and Dropbox!

2015-04-25 16.08.27

I recently bought a cheap webcam and USB hub at Frys electronics. This particular webcam (it cost me about $6) uses the RealTek chipset. leJOS 0.9.0 adds webcam support, and you can read more about it in Lawrie’s tutorial here: https://lejosnews.wordpress.com/2014/09/04/webcam-streaming/

I figured I could do one better, and capture files from the webcam, convert them to JPG and then use the Dropbox Core API to upload them into my Dropbox account. Let’s see how to do it!

I’m assuming you’ve connected your EV3 to your Dropbox as I explained in this tutorial.

Accessing the webcam

LeJOS 0.9.0 release added basic webcam support; only one webcam is supported and the images are returned in YUYV format. But that’s enough to have some fun with.  This little program will capture an image from the webcam and convert it to JPG format and then save it into the directory snapshots/with an incrementing filename. For fun you’ll also get a live image preview (in black and white) on the EV3 screen as well!

NewImage

Here I ran the Snapshot.jar from the command line. It reads the access-token.json file we created in the previous tutorial and uses that to authorise access to my Dropbox folder. When I press the ENTER button the code converts the YUYV format into JPG format, saves it to the EV3 SDcard and then uploads to Dropbox using the Dropbox API. The basics of uploading files in Dropbox is explained here: https://www.dropbox.com/developers/core/start/java

NewImage

The picture above shows what the output is – as you capture images they are uploaded into Dropbox and appear in Finder on my Mac always instantly. The images are at a 160×120 resolution as that is the size of the EV3 screen, but the camera supports much higher res images. Behold The Power of the Cloud!

The Code

The Java code is a combination of the leJOS webcam streaming tutorial code and the Dropbox Java tutorial code. Not the prettiest I’ll admit…

import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Locale;

import javax.imageio.ImageIO;

import lejos.hardware.BrickFinder;
import lejos.hardware.Button;
import lejos.hardware.Sound;
import lejos.hardware.ev3.EV3;
import lejos.hardware.lcd.GraphicsLCD;
import lejos.hardware.lcd.LCD;
import lejos.hardware.video.Video;
import lejos.hardware.video.YUYVImage;

import com.dropbox.core.*;
import com.dropbox.core.json.JsonReader;
import com.dropbox.core.util.IOUtil;

/**
 * Use a cheap webcam to take a snapshot and send the image to Dropbox.
 * Requires a Dropbox authorisation token to be created
 * EV3 needs to be connected to the wifi and the webcam connected too.
 * Requires leJOS 0.9.0 release and some setup. 
 * See http://thinkbricks.net/set-up-dropbox-in-lejos-on-the-ev3 for Dropbox-leJOS setup
 * 
 * Press ENTER button to take a photo. You should see it appear in your Dropbox folder
 * 
 * @author mcrosbie
 * http://thinkbricks.net
 * April 2015
 */

public class Snapshot {
   private static final int WIDTH = 160;
   private static final int HEIGHT = 120;
   private static int NUM_PIXELS = WIDTH * HEIGHT;
   private static int FRAME_SIZE = NUM_PIXELS * 2;
   private static final String AUTHFILENAME = "./access-token.json";
   private static final String FILENAME = "snapshots/snapshot_";

   public static void main(String args[]) throws IOException, DbxException {
	   int ret = _main(args);
	   System.exit(ret);
   }
   
   public static int _main(String[] args) throws IOException, DbxException  {
       int frames = 0;
       int threshold;
              
       // Default to access token file if not on cmd line
       String argAuthFile;
	   if (args.length != 1) {
		   argAuthFile = AUTHFILENAME;
	   } else {
		   argAuthFile = args[0];
	   }

       System.out.println("Reading auth info file " + argAuthFile);
       // Read auth info file.
       DbxAuthInfo authInfo;
       try {
           authInfo = DbxAuthInfo.Reader.readFromFile(argAuthFile);
       } catch (JsonReader.FileLoadException ex) {
         System.err.println("Error loading : " + ex.getMessage());
         return 1;
       }
       
       System.out.println("Creating Dropbox client...");

       // Create a DbxClient to make API calls.
       String userLocale = Locale.getDefault().toString();
       DbxRequestConfig requestConfig = new DbxRequestConfig("Snapshot", userLocale);
       DbxClient dbxClient = new DbxClient(requestConfig, authInfo.accessToken, authInfo.host);
 
       System.out.println("Open video camera...");
       // Get the video device and open the stream
       Video video = BrickFinder.getDefault().getVideo();
       video.open(WIDTH, HEIGHT);
     
       // Create the frame buffer to hold the image in
       byte[] frame = video.createFrame();
       BufferedImage img = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
       YUYVImage yuyvImg = new YUYVImage(frame, video.getWidth(), video.getHeight());

       GraphicsLCD g = BrickFinder.getDefault().getGraphicsLCD();

       // Keep displaying an image. 
       // Save a file to storage when enter is pressed
       // Escape to exit
       g.clear();
       System.out.println("Starting main capture loop...");
       while (!Button.ESCAPE.isDown()) {
    	   try {
               video.grabFrame(frame);
               
               // Display on the EV3 screen
               threshold = yuyvImg.getMeanY();
               yuyvImg.display(g, 0, 0, threshold);
               
              if (Button.ENTER.isDown()) {
            	  Sound.playTone(500, 100);
                  for(int i=0;i255? 255 : r<0 ? 0 : r;
       g = g>255? 255 : g<0 ? 0 : g;
       b = b>255? 255 : b<0 ? 0 : b;
       return 0xff000000 | (r<<16) | (g<<8) | b;
   }

 }