Time-Based Sculpture – Progress Report

Posted: April 27th, 2011 | Author: genevieve | Filed under: Comp Cameras, Nature of Code | No Comments »

For my Nature of Code final, I decided to pursue the gestural approach to create a time-based sculpture by experimenting with the Kinect and its point cloud capabilities for 3D printing. After doing some initial research into best options for this approach, I was pointed to work done by students in the 3D Sensing class taught by Zach Lieberman and Kyle McDonald this spring. Kyle has some code posted on github that generates a .ply file of a point cloud, which you can bring into Meshlab (open source 3D modeling software) to generate a surface mesh for printing. You can download the bundle for the whole class. The code I used is from week 6, called PlyExporter.

Now, I was able to get the code running in OpenFrameworks, and did get some .PLY files into MeshLab. However, since I am interested in capturing a gesture over time, I needed to change the code in order to capture the points from multiple frames in a short span of time. Just pressing the record button multiple times didn’t quite capture the fluidity I was looking for. Since I’ve never coded in OpenFrameworks before, I decided to see if I could something like this working in Processing. After consulting the internet for a bit, I found a tutorial that claimed to do this very thing.

The example code available on the site uses an older version of Shiffman’s kinect library for processing, so unfortunately I wasn’t able to get it running until Shiffman was kind enough to look it over and update the syntax. The original code accessed the Depth Image and stepped through the pixels. The brighter the pixel value, the “closer” the pixel is in 3D space. The updated code is adapted from the Point Cloud example, and accesses the depth value array instead of scaling the brightness of the Depth Image values to render the point cloud into 3d space. The point cloud example makes use of the DepthToWorld() function, that translates what the Kinect sees as values from 0 to 2048 into meters.

Here is the code Shiffman updated which exports an .OBJ file of the point cloud in view after pressing the ‘R’ key. You will need to download the openkinect library, the PeasyCam library, and the SuperCAD library.

/*
 Genevieve Hoffman - Point Cloud to OBJ file, Nature of Code Final Project 2011
 
 Based on Simple Kinect point-cloud demo v. 0.2, by Henry Palonen <h@yty.net>
 
 Using Daniel Shiffman’s great processing-library for Kinect and Point Cloud Example:
 
 http://www.shiffman.net/p5/kinect/
 
 Based on Kyle McDonalds Structure Light scanner:
 
 http://www.openprocessing.org/visuals/?visualID=1014
 
 Using also SuperCAD for outputting the .obj – files:
 http://labelle.spacekit.ca/supercad/
 
 History
 ——-
 17.11.2010 – 0.1 – First version, simple point-cloud working
 18.11.2010 – 0.2 – Output to .obj for importing to Blender,
 gray-color for distance and small lines as output
 
 */
 
import peasy.*;
import org.openkinect.*;
import org.openkinect.processing.*;
import superCAD.*;
 
boolean record = false;
 
float zscale = 3;
float zskew = 100;
 
int inputWidth = 640;
int inputHeight = 480;
 
PeasyCam cam;
 
PVector[][] gray = new PVector[inputHeight][inputWidth];
 
// We'll use a lookup table so that we don't have to repeat the math over and over
float[] depthLookUp = new float[2048];
 
 
PImage depth;
 
static final int gray(color value) {
  return max((value >> 16) & 0xff, (value >> 8 ) & 0xff, value & 0xff);
}
 
Kinect kinect;
 
 
void setup() {
  size(inputWidth, inputHeight, P3D);
  background(0);
  cam = new PeasyCam(this, width*2.5);
  kinect = new Kinect(this);
  kinect.start();
  kinect.enableDepth(true);
  //depth = createImage(640, 480, RGB);
  stroke(255);
  // Lookup table for all possible depth values (0 - 2047)
  for (int i = 0; i < depthLookUp.length; i++) {
    depthLookUp[i] = rawDepthToMeters(i);
  }
}
 
int counter = 0;
 
void draw () {
  background(0);
  if (record == true) {
    beginRaw("superCAD.ObjFile", "Rhazes_" + counter + ".obj"); //Start recording to the file
  }
 
  //depth.pixels = NativeKinect.getDepthMap();
  //depth.updatePixels();
  //depth = kinect.getDepthImage();
  int[] depth = kinect.getRawDepth();
 
  for (int y = 0; y < inputHeight; y++) {
    for (int x = 0; x < inputWidth; x++) {
      int offset = x+y*inputWidth;
      // Convert kinect data to world xyz coordinate
      int rawDepth = depth[offset];
      PVector v = depthToWorld(x,y,rawDepth);
      gray[y][x] = v;
    }
  }
 
 
  float scaling = 200;
 
  // Kyle McDonald’s original source used here
  translate(-inputWidth / 2, -inputHeight / 2);
  int step = 2;
  for (int y = step; y < inputHeight; y += step) {
    float planephase = 0.5 - (y-(inputHeight / 2)) / zskew;
    for (int x = step; x < inputWidth; x += step)
    {
      stroke(255);
      //point(x, y, (gray[y][x] - planephase) * zscale);
 
      PVector v = PVector.mult(gray[y][x],200);
 
      if (v.z > 100 && v.z < 200) {
        line(v.x,v.y,v.z,v.x,v.y,v.z);
        //line(gray[y][x].x,gray[y][x].y, gray[y][x].z,gray[y][x].x,gray[y][x].y, gray[y][x].z);
      }
    }
  }
 
  if (record == true) {
    endRaw();
    record = false; // Stop recording to the file
  }
}
 
void keyPressed() {
  if (key == 'R' || key == 'r') {
    // Press R to save the file
    record = true;
    counter++;  //Thanks to Dr. Rhazes Spell for putting the counter in adding functionality.
  }
}
 
// These functions come from: http://graphics.stanford.edu/~mdfisher/Kinect.html
float rawDepthToMeters(int depthValue) {
  if (depthValue < 2047) {
    return (float)(1.0 / ((double)(depthValue) * -0.0030711016 + 3.3309495161));
  }
  return 0.0f;
}
 
PVector depthToWorld(int x, int y, int depthValue) {
 
  final double fx_d = 1.0 / 5.9421434211923247e+02;
  final double fy_d = 1.0 / 5.9104053696870778e+02;
  final double cx_d = 3.3930780975300314e+02;
  final double cy_d = 2.4273913761751615e+02;
 
  PVector result = new PVector();
  double depth =  depthLookUp[depthValue];//rawDepthToMeters(depthValue);
  result.x = (float)((x - cx_d) * depth * fx_d);
  result.y = (float)((y - cy_d) * depth * fy_d);
  result.z = (float)(depth);
  return result;
}

After you export the .OBJ file, the next step is to bring it into MeshLab to clean up the points and generate a surface mesh, which you need in order to print 3D. I recommend checking out Kyle’s useful tutorial that explains some of the processes you need to go through in MeshLab to take generate a surface mesh for the exported point cloud. If you want to give this method a try, I highly recommend watching his tutorial before trying to figure out MeshLab on your own.

Since my goal was to capture a three-dimensional gesture over time, I ended up changing the code posted above a bit in order to export multiple frames of point clouds. I’m happy to post the code, but I’m not sure it’s quite at the state to be most useful, since I haven’t been able to implement controls for how many points to add to the arraylist which gets exported.

The code exports many .OBJ files, about the same as the amount of frames the code has been running for. Next I opened up MeshLab and imported the .OBJ files to see what they looked like and how they might fit together. MeshLab, though it is freeware, has a ton of options about how to create meshes from point clouds. Again, I went off from Kyle’s tutorial, but the basic workflow for joining multiple point clouds is get rid of all extra points with the select and delete functions. Once you have the point cloud looking for the most part how you want it, calculate the normals for the points. By default, the normals should draw behind the points (this wasn’t quite true for me since I had so many points). Next you recalculate the normals, the generate a mesh. There are a ton of ways to do this, and I spent a lot of time trying to figure out which method would yield the results that I wanted. Kyle’s workflow didn’t quite end up working for me since I had so many interior points built up, so I experimented a lot with other methods of building surface meshes.

Here are some screenshots of my workflow and process. The point cloud captures two hands coming together in a sort of prayer-like gesture.

Point Cloud brought into MeshLab

Point Cloud Downsampled with Poisson-Disk Sampling

Side View of Point Cloud in Mesh Lab

Poisson Surface Reconstruction - following Kyle McDonald's Tutorial, getting weird results

Mesh View after VCG Surface Reconstruction - still artifacty

Textured Mesh View after Alpha Complex Reconstruction - very polygonal

Surface Mesh View after Marching Cubes (APSS) Reconstruction - getting better

Textured Mesh View after Marching Cubes (APSS) Reconstruction

Textured Mesh View after Marching Cubes (APSS) Reconstruction - adjusting parameters

Surface Mesh View after Marching Cubes (APSS) Surface Reconstruction - almost there

Textured Mesh View after Marching Cubes (APSS) Surface Reconstruction - better parameters

Basically, it comes down to being able to use a 3D modeling program to create the best surface mesh you can from the point cloud. My time-based point cloud and all its points inside the object (which I was going to start erasing in MeshLab to see how that would work but didn’t quite have time) is confusing for the 3D modeling software because it wants to draw polygons connection all those points as well. I had to choose between spending the time to do that in the modeling software, or figuring out a smarter way to capture a point cloud on the processing side. Since just capturing a point cloud gives me too many points, I realized that a combination of a perimeter over time, with a point cloud for the “end point” might be the best method. OpenCV blob tracking will do this pretty easily. I was going to start coding this, and then I found this project on the internet.

The people who also brought you the Kinect puzzle pieces wrote software to trace the perimeter of an object and draw it over time in 3D space. They have also kindly posted their source code, which is in OpenFrameworks, on the website. At this point I have the code running in OpenFrameworks and am doing tests to see what I can capture, and how best to do this.

Hopefully I will have some models to test print in the next few days, in the meantime, here is a video of the software in action:

Special thanks to Corrie Van Sice, Ezer Lichtenstein, Greg Borenstein, Nikolas Psaroudakis, and Dan Shiffman for their help and advice throughout this process.


Tidal and Ocean Wave Power

Posted: April 21st, 2011 | Author: genevieve | Filed under: Sustainable Energy | 2 Comments »

Tidal Power is the ability to harness the potential energy created between the moon the Earth as they rotate around the Sun. Most of the energies we’ve talked about in class are dependent upon the Sun. Fossil Fuels, Wind power, Thermal Energy, Solar Power, and Bio-Fuels are all bi-products of the sun or some solar process. Nuclear power is of course a chemical reaction. Geo-Thermal is taps into the convection occurrence at the Earth’s core. Tidal power on the other hand is “the only technology that draws on potential energy inherent in the orbital characteristics of the Earth–Moon system.”

The moon is majorly responsible for the changing of the tides. When the planet rotates, the portion of the Earth that is facing the moon changes, which in turn creates a change in the distribution of water on the earth. Because water is a liquid, it is susceptible to the gravitational pull of the moon and a change in the Tidal level occurs. In other words, the level of the ocean at a specific place on the Earth changes height twice a day.

Tidal power takes advantage of this height differential and uses it to generate power. To be clear, Tidal power is categorically different than “Wave Power.” “Wave power devices extract energy directly from surface waves or from pressure fluctuations below the surface.” [1] Basically, wave power uses the motion at the surface of the ocean to create energy.

Like any other type of energy generation, the flow of water pushes a magnet back and forth past a large coil to excite electrons. Tidal Power is defined by the ebb and flow of the currents in the ocean in combination with the height of the water level. Since the ocean amounts for 70% of the Earth’s surface, there is amazing potential to use this resource to generate power for a variety of reasons. Tides are extremely consistent and therefore more reliable than any wind or solar options. Because you’re using the existing movement of the tides, Tidal power is a source of energy that’s available indefinitely. Certain coastal cities are prime candidates for tidal power, providing options for areas that aren’t able to take advantage of wind or solar power farms.

Tidal Energy cannot be harvested just anywhere, however. In fact, there are only about 40 sites suitable for tidal power plants since there needs to be height difference of at least 16 feet (5 meters) between low and high tides. [2]

There are very specific conditions for collecting the ocean’s potential energy and those conditions have engineered very different mechanisms for harvesting the energy.

1. A “Barrage System”
A barrage is a method of harvesting the difference in wave height between low and high tide. Essentially a dam along an estuary, this system has many environmental impacts not to mention extremely limited suitable sites worldwide. As the water level is lower on the ocean side of the barrage, the water wants to return to equilibrium. By forcing the water to flow past a turbine, energy is generated when the tide is low and water moves from the “basin” or estuary side to towards the ocean.

The first Tidal Power Plant began operation in 1966 in Brittany, France as a Barrage system. Today it is still in operation as the largest Tidal Power Station in the world. With a peak rating of 240 Megawatts, generated by its 24 turbines, it supplies 0.012% of the power demand of France. Its capacity factor of approximately 40% allows it to supply an average 96 Megawatts, giving an annual output of approximately 600 GWh.

As mentioned, the sites which are capable of supporting a Tidal Barrage are limited. Some prospective sites for Barrages can be found here.

2. Tidal Stream Generator
The second type of Tidal Power mechanism is a tidal stream generator and requires the least amount of infrastructure among the three main forms of tidal power generation. Like a wind turbine, the tidal stream generator (often called a Tidal Turbine) makes use of water flowing across an underwater blade. Unlike wind turbines, though, Tidal Turbines can be turned horizontally to take advantage of of the currents that flow laterally. Because water has a much higher density than wind (about 800 times more dense), it can generate a large amount of kinetic power. In fact, “water speeds of nearly one-tenth of the speed of wind provide the same power for the same size of turbine system.”[3] These devices are best installed in channels, between islands or in estuaries, where the current is forced to move past the turbines.

Sites that have been selected as optimal for Tidal Stream Generation:

    Pembrokeshire in Wales
    River Severn between Wales and England
    Cook Strait in New Zealand
    Kaipara Harbour in New Zealand
    Bay of Fundy in Canada.
    East River in the USA
    Golden Gate in the San Francisco Bay
    Piscataqua River in New Hampshire
    The Race of Alderney and The Swinge in the Channel Islands
    The Sound of Islay, between Islay and Jura in Scotland
    Pentland Firth between Caithness and the Orkney Islands, Scotland
    Humboldt County, California in the United States
    Columbia River, Oregon in the United States

There are a variety of fans and oscillators used for tidal stream generation systems. The outer two turbines shown here are known as VAWT or vertical axis wind turbines, whereas the centered turbine is operates on the horizontal axis.

Here you can also see a rendering of an underwater kite, which is tethered to the ocean floor and has turbines on its wings. By tethering the turbines and moving them around, it increases the flow of current flowing through, keeping the turbines active at all times. There is an increased payback for a smaller package. This device generates the same amount of power in 3 weeks as an onshore wind turbine does in 8 months.

In 2007 Verdant Power began operating a prototype in the East River between Roosevelt Island and Queens, which is the first tidal project in an major US urban area. The prototype has seen some challenges though. The blades of an earlier prototype broke off and were replaced with more robust turbines in 2008. The company holds a patent for devices that generate power in slower moving canals and waterways.

Current Tidal Harvesting Projects:

In March a project was approved to create the “first of its kind” wind farm off the coast of Scotland. The size of the project is what is monumental here, not necessarily the technology as they will be using devices that have been in operation for over six years.

3. Dynamic Tidal Power
The third type of Tidal Power harvesting is still mostly a theoretical proposal. As of yet, this system has not been implemented. The proposal is to create a T-shaped structure which intersects the coast perpendicularly, as opposed to a regular barrage dam which is parallel to the coast. The T-shape part extends into the ocean, and does not fully enclose the water but instead, creates a phase difference of tides on each side of the structure. In this way you are able to create a barrier that does not completely contain the water, but rather creates an artificial difference in the water level. The water is then moved in a similar way as the barrage, past a turbine to generate power. This concept is enticing because it allows for Tidal Power in areas where there is a large coastline, but not a estuary. Each dam would generate between “6-15 GW.” [3]

Tides move parallel to the shoreline in most places, not perpendicularly. If you are able to impeded the movement of the tide as it’s moving outward you’re able to create a height differential and direct the flow through turbines in order to reach equilibrium on either side of the DBT.

Wave Power
“Wave power devices extract energy directly from surface waves or from pressure fluctuations below the surface. Renewable energy analysts believe there is enough energy in the ocean waves to provide up to 2 terawatts of electricity. (A terawatt is equal to a trillion watts.)

Wave power can’t be harnessed everywhere. Wave-power rich areas of the world include the western coasts of Scotland, northern Canada, southern Africa, Australia, and the northeastern and northwestern coasts of the United States. In the Pacific Northwest alone, it’s feasible that wave energy could produce 40–70 kilowatts (kW) per meter (3.3 feet) of western coastline. The West Coast of the United States is more than a 1,000 miles long.” [4]

There are two main types of wave power generation, offshore systems and onshore systems.

1. Offshore Systems
Offshore Systems generate power by harnessing the movement of the water’s surface to turn generators. One example of this is the Salter Duck, a device which sits on top of the waves, and bobs up and down, the motion of which turns a turbine inside of it attached to a generator.

Another example is the Scottish developed Pelamis, which is currently part of the first large-scale commercial wave power farm off the coast of Portugal, which “will generate clean electricity for more than 1,000 family homes in its first phase.” [5]

2. Onshore Systems
Onshore systems generate power by harnessing the energy in breaking waves. There are various types of mechanisms that do this, among them are:

- Oscillating Water Column: “The oscillating water column consists of a partially submerged concrete or steel structure that has an opening to the sea below the waterline. It encloses a column of air above a column of water. As waves enter the air column, they cause the water column to rise and fall. This alternately compresses and depressurizes the air column. As the wave retreats, the air is drawn back through the turbine as a result of the reduced air pressure on the ocean side of the turbine.” [6]

- Tapchan: A tapered channel system where water is fed through a channel into a reservoir, usually on top of cliffs. The height difference causes water

- Pendulor Device: A an open box with a lid facing the sea. Waves traveling back and forth cause the lid to move on hinges, which powers a generator.

Also, there is the potential for partnership between offshore oil and gas companies, since they have already researched deep sea conditions. [7]

Resources:
World Energy Council Report on Tidal Energy: http://www.worldenergy.org/publications/survey_of_energy_resources_2007/tidal_energy/default.asp

Wikipedia page on Tidal Power: http://en.wikipedia.org/wiki/Tidal_power

List of Operating Tidal Power Plants: http://en.wikipedia.org/wiki/List_of_tidal_power_stations


Computational Cameras Final Proposal – Darkness Map Mobile App

Posted: April 19th, 2011 | Author: genevieve | Filed under: Comp Cameras | No Comments »

For my final project in Computational Cameras, I am going to write a mobile app for Android that serves as the sensing device to collect data for the Darkness Map project. The Darkness Map is a mapping project to visualize the light and dark areas of New York City at night.

I began this project last semester, as a collaboration with Scott Wayne Indiana and Rune Madsen. For a proof of concept, Scott and I walked the streets of Manhattan on either side of the street, pointing a digital video camera at the other side of the street as we walked. We began recording at the beginning of a block, and stopped recording at the end. Using voice tagging (ie, we spoke into the camera which streets we were walking on), we kept track of clips. Rune then processed each clip with an algorithm that averaged the brightness of each frame, then output a histogram graphing these values. More information detailing this process can be found here, here and here.

At this stage I am trying to design an application that will be both functional in terms of data collection, and encourage users to participate in crowd sourcing data collection for the map.

A few of the technical requirements I hope to integrate into the mobile app:
- Disabling auto-gain on the camera. The Darkness Map needs to be relatively controlled, so that the light and dark readings are accurate for different users at different times.
- Tagging the first and last frame of the clip with GPS data. Since GPS isn’t entirely predictable or accurate, I want to tag each frame with GPS within the clip if the GPS location changes.
- Processing each frame for average brightness and saving this value.
- Keeping track of the millis() since the clip began, and tagging each frame with the millis() value
- If possible, tagging each frame with a Real Time Clock value, so that I can compare lightness and darkness readings at various times of night.

In order to encourage user participation, I would also like to integrate the following:
- Tag each brightness reading with a Username, so that people can see who has added to the map
- Possibly integrate game mechanics in order to encourage competition to see who can map the most area

Possible Extensions for this or future iterations:
- Keep track of average RGB values of each clip in order to map the color of the city. There is the possibility of having this occur during daylight as well.

Here is a pdf of wireframes demonstrating the design and user interaction of the Darkness Map Mobile App:
DarknessMapWireframes


Sustainable Energy Final Project Progress

Posted: April 14th, 2011 | Author: genevieve | Filed under: Sustainable Energy | No Comments »

Working Project Title : Peaks and Valleys

Metrics: Measure the potential energy the solar panel generates over time, and use this data to create a compelling data driven sculpture.

Alternate concept: Focus on form of ferrofluid and make a solar driven sundial, with magnets attached to servo motors that turn when different sized capacitors discharge.

Gabriella Levine and I are working together to make a data visualization of a large solar panel which we are borrowing from Dave Miller. The panel outputs around 20V at peak sunlight, and we believe we found its correct spec online, which says it outputs 4.5 watts max. We want to collect this data to see what its potential power is over the course of a few weeks as the weather changes. Here is a graph of data we’ve collected over a few days.

Solar Panel Voltage visualized over a few days

Solar Panel Voltage visualized over a few days

We may add a temperature / humidity sensor to see how that corresponds with voltage as well. More on that later.

The other component of this piece is the data visualization. We would like to make a physical sculpture to visualize this data, ideally made with ferrofluid. Ferrofluid is an amazing medium – essentially tiny magnetic particles suspended in liquid. When they are near a magnetic field, the liquid takes on spike-like patterns, whose heights and proximity depend upon the strength of the magnetic field.

Ideally, we want to use electromagnets to activate the data visualization. The electromagnets would be beneath a basin of ferrofluid. We would send varied voltage through them according to the data from the solar panel. Hopefully we could make the visualization run through the ferrofluid like a standing wave. One thing we need to keep in mind is that “graphing” our data with ferrofluid drastically reduces the resolution. Actually, in order to collect our data in the first place we are dividing the voltage by about 5.7 with a voltage divider (2 resistors whose values are in proportion of 1:5.7). However, this makes is so we don’t blow up our Arduino, and if we want to play the data back, that would be the voltage we could send from the Arduino anyway.

Here are some photos of tests we’ve done with ferrofluid, to see what magnets and movements affect what kind of patterns.

ferrofluid with electromagnet beneath


Nature of Code Final Proposal

Posted: April 13th, 2011 | Author: genevieve | Filed under: Nature of Code | No Comments »

For my final project in Nature of Code, I would like to try and make a time-based sculpture. Many time-based sculptures involve aspects of traditional time-based media, like video or sound. I want to try and make a static sculpture that embodies a time-based process. There are two directions I am thinking of going in to achieve this.

1. Generative

I want to experiment with a few generative algorithms and draw their process of evolution out in 3D space. Possible algorithmic models I’m looking at are Cellular Automata, Reaction-Diffusion (also known as the Gray Scott model), and 3D fractals.

In my research, I came across the work of computational architect Michael Hansmeyer. I am especially interested in his Platonic Solids series, which takes a traditional Platonic Solid, and performs an iterative process subdividing its faces into more faces, essentially generating a three-dimensional fractal. This process, like fractal patterns in nature, generates amazing complexity from a simple process. He varies the value which is performing the operation, which produces more variation over time.

2. Gestural

Another direction I am considering is trying to make a sculpture that captures a moving gesture. I am interested in trying to make the ephemeral tangible, or more permanent. I am also interested to see what capturing a motion over time would look like when it’s layered over itself. My instinct is that it would turn something recognizable, like a hand, into something more abstract.

Working from the Point Cloud example for the Kinect, my goal would be to visualize and save the data points from multiple frames. I would most likely export these into a 3D modeling program to see what it would like, and perform any smoothing. I see this project as an experimental framework, since I’m not completely sure what sorts of gestures are worth “saving,” and what types of abstractions might appear.

Here is video documenting some works by the artist Koki Tanaka. Since the late 60s, video has been the primary form to document time-based performance sculptures. The result of these works is a record of the action, not the goal of the works, and most often secondary to the process itself.

Here is another video piece (sorry about the ad), focused on simple hand gestures. This might be a direction I experiment with once the framework is functional. Hands have always fascinated me in their complexity and utility. It would be interesting to try some video experiments with hands holding various tools – pencils, water glasses, knitting needles.


Gesture-Sculpture by bernardperroud

3. Gesturally generative

A third direction I am considering is to control a 3D particle system, or flow field, with physical gestures. I’m not sure if the final output would be sculptural, but I do think it would be an interesting experiment to affect a three-dimensional environment.

Here is a video of a 3D flow field by Reza Ali.

Apparently this direction is being taken by research done at Microsoft, surprise surprise.


Where-Able Camera

Posted: April 5th, 2011 | Author: genevieve | Filed under: Comp Cameras | No Comments »

I took this week’s assignment in Computational Cameras as an opportunity to do some of the groundwork for a mobile application I would like to implement for my final project. My goal for the assignment was to tag video taken on the phone with a GPS location. However, I did not quite get that far. It turns out that programming for Android in Processing, or Android in Eclipse is somewhat tricky. Setting up the SDK was straightforward enough, and there are a few good tutorials out there. The main tutorial linked to on the Android Processing website is helpful, but also meant for an Eclipse IDE. I found Jer Thorp’s tutorial about setting up Android on Processing to be pretty helpful.

So, the next tool I tried to incorporate was the Ketai library, which allows you to access a number of the mobile phone’s sensors. I was primarily interested in accessing the camera, so I started out with this example code. Remember to drag the ketai.jar file into the sketch window, which will create a folder inside the sketch folder called “code,” which should contain the jar file. One thing to keep in mind as well, which will probably frustrate you a lot, is to make sure you enable the sketch permissions for the camera. Go to “Android” in the toolbar, then “Sketch Permissions.” There are many options, but scroll down and check the box next to camera. These are essentially the permissions that the user must allow in order for your sketch to access the mobile phone’s camera, location, accelerometer, and other sensors. Another thing to keep in mind is that after you’ve installed the “Available Packages” in the Android AVD Manager (accessible in Processing by opening the android sdk folder, then tools, then selecting “android,” which will open a Terminal window as well as the AVD Manager), you also need to make a new “Virtual Device.” This device needs to be called Processing-Android-7, but can target any version of Android after version 7 (I’m running Android 2.1). Here’s a link to a forum post about this very issue.

Eric Pavey’s code was helpful. He coded his own camera example by modifying the Ketai source code. I also found some code by Golan Levin that did some brightness tracking. I modified this code to average the brightness of each frame of the camera view, which is the algorithm I want to use to make my mobile sensor for the Darkness Map app. Unfortunately I did not get much further than this. Here is the code that I was able to get running.

// Modified from Golan Levin's Brightness Tracking code
import edu.uic.ketai.inputService.KetaiCamera; 
 
KetaiCamera cam;
int numPixels;
int[] previousFrame;
int averageBrightness = 0;
void setup() 
{
  orientation(LANDSCAPE);
  cam = new KetaiCamera(this, 320, 240, 24);
  numPixels = cam.width * cam.height;
  previousFrame = new int[numPixels];
 
  background(0);
}
 
void draw() 
{
  cam.loadPixels(); 
  int brightestX = 0;
  int brightestY = 0;
  float brightestValue = 0;
  int index = 0;
  averageBrightness = 0;
  for (int i = 0; i < cam.height; i++) {
    for (int j = 0; j < cam.width; j++) {
      int pixelValue = cam.pixels[index];
      float pixelBrightness = brightness(pixelValue);
 
      averageBrightness += pixelBrightness;
 
      if (pixelBrightness > brightestValue) {
        brightestValue = pixelBrightness;
        brightestY = i;
        brightestX = j;
      }
      index++;
    }
  }
 averageBrightness =  averageBrightness / index;
  cam.updatePixels();
  image(cam, 0, 0, screenWidth, screenHeight);
  int x = (int)map(brightestX, 0, cam.width, 0, screenWidth);
  int y = (int)map(brightestY, 0, cam.height, 0, screenHeight);
  fill(averageBrightness);
  rectMode(CORNER);
  rect(0, screenHeight - 100, screenWidth, screenHeight);
}
/*
void onCameraPreviewEvent()
 {
 cam.read();
 cam.loadPixels();
 image(cam, 0, 0, screenWidth, screenHeight);
 
 int brightestX = 0;
 int brightestY = 0;
 float brightestValue = 0;
 
 int index = 0;
 for(int i = 0; i < cam.height; i++) {
 for(int j = 0; j < cam.width; j++) {
 int pixelValue = cam.pixels[index];
 float pixelBrightness = brightness(pixelValue);
 if (pixelBrightness > brightestValue) {
 brightestValue = pixelBrightness;
 brightestY = i;
 brightestX = j;
 }
 index++;
 }  
 }
 fill(255);
 ellipse(brightestX, brightestY, 100,100);
 
 }
 */
 
 
void onCameraPreviewEvent()
{
  cam.read();
}
 
void exit() 
{
  cam.stop();
}
 
// start/stop camera preview by tapping the screen
void mousePressed()
{
  if (cam.isStarted())
  {
    cam.stop();
  }
  else
    cam.start();
}

Even though I wasn’t able to combine GPS tags with video, I was able to get gps example code to run on my phone. I decided to test what kind of accuracy, or what kinds of readings it would give me in different locations.

GPS Example Phone App

Here's the GPS reading at my apartment in Brooklyn

GPS Example Mobile App

Here's the GPS reading at the lovely Third Rail Coffee in the West Village

I think I need to look into GPS a bit more, because the readings don’t seem all that different to me. Perhaps the Google Map API is the way to go.