<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dan O&#039;Sullivan</title>
	<atom:link href="http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=44" rel="self" type="application/rss+xml" />
	<link>http://itp.nyu.edu/~dbo3/blog</link>
	<description></description>
	<lastBuildDate>Tue, 17 Jul 2012 18:33:25 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.1</generator>
		<item>
		<title>Page Ghosts</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=131</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=131#comments</comments>
		<pubDate>Thu, 27 Aug 2009 18:28:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=131</guid>
		<description><![CDATA[If you have a web cam you can got to http://itp.nyu.edu/dano/face to hover over a web with other people looking at that some page.  Your video image follows your cursor around the page tuning in other video images more sharply when they are close to you on the page.  This needs a Flash 10 plugin.]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-medium wp-image-130" title="pageGhost" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/pageGhost1-300x244.jpg" alt="pageGhost" width="300" height="244" /></p>
<p>If you have a web cam you can got to <a href="http://itp.nyu.edu/dano/face/index.html">http://itp.nyu.edu/dano/face</a> to hover over a web with other people looking at that some page.  Your video image follows your cursor around the page tuning in other video images more sharply when they are close to you on the page.  This needs a Flash 10 plugin.</p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=131</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Camera Hat for Complicated Televisions</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=122</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=122#comments</comments>
		<pubDate>Tue, 13 Jan 2009 17:01:30 +0000</pubDate>
		<dc:creator></dc:creator>
				<category><![CDATA[Pressure Projects]]></category>
		<category><![CDATA[Webcam]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=122</guid>
		<description><![CDATA[I have a Master&#8217;s Degree in Interactive Telecommunications so I get a lot of calls to help people with their technical systems.  These calls are mostly from my Mom wanting to watch TV and they mostly result from her not understanding the universal remote.  My life on the family AV squad would be helped if [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone" src="http://itp.nyu.edu/dano/blog/wp-content/uploads/gPhoneHat.jpg" alt="" /></p>
<p>I have a Master&#8217;s Degree in Interactive Telecommunications so I get a lot of calls to help people with their technical systems.  These calls are mostly from my Mom wanting to watch TV and they mostly result from her not understanding the universal remote.  My life on the family AV squad would be helped if I could see what she sees when she calls.  I thought it would be nice to give her a hat with a camera in it.  My first thought was one of those swell <a href="http://www.axis.com/products/cam_207w/index.htm">network cameras.</a> They are small wireless and I would not have to do any of the netwoking.  Unfortunately my Mom does not have an Internet connection.  My next thought was to use some the solutions that the <a href="http://en.wikipedia.org/wiki/Lifecasting_(video_stream)">lifecasting</a> folks are using like <a href="http://qik.com/">Qik</a> but I don&#8217;t think that can stream to another phone and she usually need help when I am out and about.  Also I kind of wanted learn how to program for Android so I decided to do it myself on one of those.  I did it as a one day project for ITP&#8217;s <a href="http://itp.nyu.edu/ITPedia/4in4">4in4</a>.</p>
<p><span id="more-122"></span></p>
<p>Before you say how ridiculous it makes people look remember that she is usually in the privacy of her own home and does not have to wear it all the time like the lifecasters.  I only got as far as uploading pictures to the server so you have to watch on a constantly refreshing web browser.  Eventually I would like to be able to point on my phone&#8217;s touch screen and have that be reflected by a laser pointer on the camera side.  The code is mostly mushing together the <a href="http://code.google.com/android/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html">Camera Preview</a> example from the Android api examples and <a href="http://www.anddev.org/upload_files_to_web_server-t443-s15.html">this tutorial</a> for uploading files.  I will past the code below.  I looked at some of the getting started stuff but I got  YALF (yet another language fatigue) thinking about activities and views and intents.  Somehow I got it done without understanding any of that.  My biggest headache was in getting the manifest right when I added another app to the a single project in Eclipse.  In the end the only way I could get it to work was to hand edit the xml in the last tab rather.<br />
package com.osullivision;</p>
<p>import java.io.DataInputStream;<br />
import java.io.DataOutputStream;<br />
import java.net.HttpURLConnection;<br />
import java.net.MalformedURLException;<br />
import java.net.URL;<br />
import java.net.URLEncoder;</p>
<p>import android.app.Activity;<br />
import android.content.Context;<br />
import android.graphics.PixelFormat;<br />
import android.hardware.Camera;<br />
import android.os.Bundle;<br />
import android.util.Log;<br />
import android.view.KeyEvent;<br />
import android.view.SurfaceHolder;<br />
import android.view.SurfaceView;<br />
import android.view.Window;</p>
<p>public class CameraHat extends Activity implements Camera.PreviewCallback, Camera.ShutterCallback, Camera.PictureCallback {</p>
<p>final String TAG = &#8220;CameraHat&#8221;;</p>
<p>Camera mCamera;</p>
<p>private Preview mPreview;</p>
<p>boolean freeToSend = true;</p>
<p>ShutterThread myShutterThread;</p>
<p>class ShutterThread extends Thread {</p>
<p>public void run(){<br />
while (true){<br />
if (freeToSend){<br />
freeToSend = false;<br />
Log.v(TAG,&#8221;thread ready&#8221;);<br />
takePicture();<br />
}<br />
}<br />
}<br />
}<br />
public void takePicture(){<br />
mCamera.takePicture(this, null, this);<br />
}<br />
@Override<br />
protected void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);</p>
<p>// Hide the window title.<br />
requestWindowFeature(Window.FEATURE_NO_TITLE);</p>
<p>// Create our Preview view and set it as the content of our activity.<br />
mCamera = Camera.open();<br />
Camera.Parameters p = mCamera.getParameters();<br />
int CAM_W = 160;<br />
int CAM_H = 120;<br />
p.setPictureSize(CAM_W, CAM_H);<br />
p.setPictureFormat(PixelFormat.JPEG);<br />
//p.setPreviewFormat(PixelFormat.JPEG);<br />
mCamera.setParameters(p);<br />
//mCamera.setPreviewCallback(this);<br />
mPreview = new Preview(this);<br />
setContentView(mPreview);<br />
myShutterThread = new ShutterThread();<br />
myShutterThread.start();<br />
}</p>
<p>// &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
@Override<br />
public boolean onKeyDown(int keycode, KeyEvent event) {<br />
Log.v(TAG, &#8220;KeyDown&#8221; + keycode);<br />
if (keycode == KeyEvent.KEYCODE_CAMERA || keycode == 8) {<br />
mCamera.takePicture(this, null, this);<br />
mCamera.startPreview();<br />
}</p>
<p>super.onKeyDown(keycode, event);<br />
return true;<br />
}</p>
<p>// private Camera.ShutterCallback sillyDelay = new Camera.ShutterCallback() {<br />
public void onPreviewFrame(byte[] data, Camera camera) {<br />
// TODO Auto-generated method stub</p>
<p>if (freeToSend){</p>
<p>freeToSend = false;<br />
Log.v(TAG,&#8221;preview&#8221;);<br />
new Uploader(&#8220;http://itp.nyu.edu/~dbo3/up.php&#8221;, data, &#8220;androidTest.jpg&#8221;);<br />
}<br />
}</p>
<p>public void onShutter() {<br />
Camera.Parameters p = mCamera.getParameters();<br />
int CAM_W = 160;<br />
int CAM_H = 120;<br />
p.setPictureSize(CAM_W, CAM_H);<br />
p.setPictureFormat(PixelFormat.JPEG);<br />
//p.setPreviewFormat(PixelFormat.JPEG);<br />
mCamera.setParameters(p);<br />
}</p>
<p>// };</p>
<p>// private Camera.PictureCallback doSomeThingWithIt = new Camera.PictureCallback() {</p>
<p>public void onPictureTaken(byte[] data, Camera camera) {<br />
Log.v(TAG, &#8220;Took Picture&#8221; + data.length);<br />
mCamera.stopPreview();<br />
new Uploader(&#8220;http://itp.nyu.edu/~dbo3/up.php&#8221;, data, &#8220;androidTest.jpg&#8221;);<br />
mCamera.startPreview();<br />
// doPost(&#8220;http://itp.nyu.edu/~dbo3/upity.php&#8221;, test.getBytes());</p>
<p>}</p>
<p>// };</p>
<p>class Preview extends SurfaceView implements SurfaceHolder.Callback {<br />
SurfaceHolder mHolder;</p>
<p>Preview(Context context) {<br />
super(context);</p>
<p>// Install a SurfaceHolder.Callback so we get notified when the<br />
// underlying surface is created and destroyed.<br />
mHolder = getHolder();<br />
mHolder.addCallback(this);<br />
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);<br />
}</p>
<p>public void surfaceCreated(SurfaceHolder holder) {<br />
// The Surface has been created, acquire the camera and tell it where<br />
// to draw.</p>
<p>mCamera.setPreviewDisplay(holder);</p>
<p>}</p>
<p>public void surfaceDestroyed(SurfaceHolder holder) {<br />
// Surface will be destroyed when we return, so stop the preview.<br />
// Because the CameraDevice object is not a shared resource, it&#8217;s very<br />
// important to release it when the activity is paused.<br />
mCamera.stopPreview();<br />
mCamera = null;<br />
}</p>
<p>public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {<br />
// Now that the size is known, set up the camera parameters and begin<br />
// the preview.<br />
//Camera.Parameters parameters = mCamera.getParameters();<br />
///parameters.setPreviewSize(w, h);<br />
//mCamera.setParameters(parameters);<br />
mCamera.startPreview();<br />
}</p>
<p>}</p>
<p>public class Uploader extends Thread {<br />
String urlString;</p>
<p>byte[] payload;</p>
<p>String fileNameOnServer;</p>
<p>public Uploader(String _urlString, byte[] _payload, String _fileNameOnServer) {<br />
urlString = _urlString;<br />
payload = _payload;<br />
fileNameOnServer = _fileNameOnServer;<br />
start();<br />
}</p>
<p>public void run() {<br />
HttpURLConnection conn = null;<br />
DataOutputStream dos = null;<br />
DataInputStream inStream = null;</p>
<p>String lineEnd = &#8220;\r\n&#8221;;<br />
String twoHyphens = &#8220;&#8211;&#8221;;<br />
String boundary = &#8220;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;29772313742745&#8243;;</p>
<p>try {<br />
// &#8212;&#8212;&#8212;&#8212;&#8212;&#8212; CLIENT REQUEST</p>
<p>URL url = new URL(urlString);<br />
// Open a HTTP connection to the URL<br />
conn = (HttpURLConnection) url.openConnection();</p>
<p>// Allow Inputs<br />
conn.setDoInput(true);<br />
// Allow Outputs<br />
conn.setDoOutput(true);<br />
// Don&#8217;t use a cached copy.<br />
conn.setUseCaches(false);<br />
// Use a post method.<br />
conn.setRequestMethod(&#8220;POST&#8221;);<br />
conn.setRequestProperty(&#8220;Connection&#8221;, &#8220;Keep-Alive&#8221;);<br />
// conn.setRequestProperty(&#8220;Cookie&#8221;, &#8220;JSESSIONID=&#8221;+PlayList.getSessionId());<br />
conn.setRequestProperty(&#8220;Content-Type&#8221;, &#8220;multipart/form-data;boundary=&#8221; + boundary);</p>
<p>dos = new DataOutputStream(conn.getOutputStream());</p>
<p>dos.writeBytes(twoHyphens + boundary + lineEnd);<br />
// dos.writeBytes(&#8220;Content-Disposition: form-data; name=\&#8221;fileNameOnServer\&#8221;"+lineEnd+URLEncoder.encode(fileNameOnServer,&#8221;UTF-8&#8243;) + lineEnd);<br />
dos.writeBytes((&#8220;Content-Disposition: form-data; name=\&#8221;data_file\&#8221;; filename=\&#8221;" + lineEnd + URLEncoder.encode(fileNameOnServer, &#8220;UTF-8&#8243;) + &#8220;\&#8221;\r\n&#8221;));<br />
dos.writeBytes(&#8220;Content-Type: &#8221; + &#8220;image/jpg&#8221; + &#8221; \r\n&#8221;);<br />
dos.writeBytes(lineEnd);<br />
//Log.v(TAG, fileNameOnServer);</p>
<p>Log.v(TAG, &#8220;Headers are written&#8221;);</p>
<p>// create a buffer of maximum size<br />
dos.write(payload);</p>
<p>dos.writeBytes(lineEnd);<br />
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);</p>
<p>// close streams<br />
Log.v(TAG, &#8220;File is written&#8221;);</p>
<p>dos.flush();<br />
dos.close();</p>
<p>} catch (MalformedURLException ex) {<br />
Log.v(TAG, &#8220;error: &#8221; + ex.getMessage(), ex);<br />
}</p>
<p>catch (Exception ioe) {<br />
Log.v(TAG, &#8220;error: &#8221; + ioe.getMessage(), ioe);<br />
}</p>
<p>// &#8212;&#8212;&#8212;&#8212;&#8212;&#8212; read the SERVER RESPONSE</p>
<p>try {<br />
inStream = new DataInputStream(conn.getInputStream());<br />
String str;</p>
<p>while ((str = inStream.readLine()) != null) {<br />
Log.v(TAG, &#8220;Server Response&#8221; + str);<br />
}<br />
inStream.close();<br />
freeToSend = true;<br />
Log.v(TAG, &#8220;FreeToSend &#8221; + freeToSend);</p>
<p>} catch (Exception ioex) {<br />
Log.v(TAG, &#8220;error: &#8221; + ioex.getMessage(), ioex);<br />
}</p>
<p>}<br />
}</p>
<p>}</p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=122</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Breath Bra</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=115</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=115#comments</comments>
		<pubDate>Fri, 03 Oct 2008 16:04:19 +0000</pubDate>
		<dc:creator>Dano</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=115</guid>
		<description><![CDATA[Breathing is surprisingly underrated.  I made this example for students in my Rest of You class to be able see their breathing on their cellphone and to  log it over the course of a day.  In the course of this I live the dream of wearing a bra on the outside of my clothes during [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/bra11.jpg"></a><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/bra12.jpg"><img class="alignright size-medium wp-image-117" title="bra12" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/bra12-300x197.jpg" alt="" width="300" height="197" /></a>Breathing is surprisingly underrated.  I made this example for students in my <a href="http://itp.nyu.edu/blogs/restofyou/">Rest of You</a> class to be able see their breathing on their cellphone and to  log it over the course of a day.  In the course of this I live the dream of wearing a bra on the outside of my clothes during class.<span id="more-115"></span></p>
<p>I used a stretch sensor attached to a bra.  I put in a temperature sensor while I was at it.  Both of them are simple variable resistors that are very easy to use with microcontrollers.  I used a <a href="http://www.arduino.cc/en/Main/ArduinoBoardLilyPad">Lilypad </a>microcontroller which is specially designed to be sewn into clothes.  There is a voltage regulator because I only had a 9 volt battery for power but it is not really necessary if you  used something like <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8786">this</a> or <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=341">this</a> instead.  Anyway instead of using a breadboard, I connected everything together by using a row of <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=115">female headers</a> bending all the ground connection to one side and the power to the other, data connections down the middle, eventually hot glue on everything.  It probably would have been easier to use <a href="http://www.cs.colorado.edu/~buechley/LilyPad/extend.html">this</a>. </p>
<p>On the software side I did the example in <a href="http://mobile.processing.org/">mobile proccessing</a> but didn&#8217;t use their library for the bluetooth connection but instead just pasted in my own class called BTThread.  To keep the code simple I wanted to avoid the whole part where one device &#8220;discovers&#8221; other devices and services.  Instead I use my laptop to find the address of the bluetooth module (it will look like &#8220;00A096179A85&#8243;) and 1 hardcoded it.  I also put some lines in there for logging the data but I commented it out because if might slow you down.   The cellphone code and also the tiny arduino code for the Lilypad is below.<br />
import java.io.IOException;<br />
import java.io.InputStream;<br />
import java.io.OutputStream;</p>
<p>import javax.microedition.io.Connector;<br />
import javax.microedition.io.StreamConnection;<br />
public class BreathBra extends PMIDlet{<br />
  String BT_ADDRESS = &#8220;00A096179Ac5&#8243;;  //use your laptop to figure out the hardware address of the blue smirf.</p>
<p>  BTThread blueTooth;</p>
<p>  int xpos;<br />
  PFont font ;<br />
  int recordNum  ;<br />
  String accumulatedFromBT = &#8220;&#8221;;</p>
<p>  public void setup(){<br />
    font = loadFont(&#8220;ArialMT-12.mvlw&#8221;);</p>
<p>    // String[] savedPlace = loadStrings(&#8220;HBSavedPlace&#8221;);<br />
    //if (getLength(savedPlace) &gt; 0) {<br />
    //   recordNum =  Integer.parseInt( savedPlace[0].trim());<br />
    //   }</p>
<p>    blueTooth = new BTThread();<br />
    blueTooth.start();</p>
<p>  }<br />
  public void draw(){</p>
<p>  }<br />
  void blueToothEvent(int input){<br />
    accumulatedFromBT = accumulatedFromBT + (char) input;<br />
    if (input == 10) {<br />
      println(&#8220;In From BlueTooth: &#8221; + accumulatedFromBT);<br />
      String[] parts = split(accumulatedFromBT,&#8221;,&#8221;);<br />
      accumulatedFromBT = &#8220;&#8221;;  //reset accumulation<br />
      //send a byte out in case other side is waiting to be prompted<br />
      blueTooth.send(65);</p>
<p>      if (getLength(parts) &gt; 1) {<br />
        try {<br />
          int breath = Integer.parseInt((parts[0].trim()))-100;<br />
          int heat = Integer.parseInt((parts[1].trim()))-400;<br />
          //  background(0);<br />
          fill(255, 255, 255);<br />
          rect(0,0,width,30); //clear the place where you are writing text<br />
          text (breath + &#8221; &#8221; + heat , 10,20);<br />
          /// saveStrings(&#8220;HBVal&#8221;+recordNum,parts);<br />
          // saveStrings(&#8220;HBSavedPlace&#8221;,new String[] {<br />
          //  String.valueOf(recordNum)                                                                                          }<br />
          // );  //recorde the last place you saved<br />
          recordNum++;<br />
          fill(0, 255, 255);<br />
          ellipse(xpos, breath, 2, 2);<br />
          fill(255, 0, 255);<br />
          ellipse(xpos, heat , 2, 2);<br />
          xpos = xpos + 2;<br />
          if (xpos &gt;= width) {<br />
            xpos = 0;<br />
            background(255,0,0);<br />
          }<br />
        }<br />
        catch (NumberFormatException e) {<br />
          println(&#8220;Not a line of Numbers&#8221;);<br />
        }<br />
      }</p>
<p>    }<br />
  }</p>
<p>  int getLength(Object[] o)  { //don&#8217;t pay attention, servicing a bug in m.p.<br />
    return o.length; //ideally you could just say yourObject.length<br />
  }<br />
  class BTThread extends Thread {<br />
    StreamConnection btConnection = null;<br />
    OutputStream btOutputStream = null;<br />
    /* thread to accumulate bytes  */</p>
<p>    public void run() {<br />
      textFont(font);</p>
<p>      try {<br />
        //surrounds hardware address in bluetooth stuff. &#8220;:01&#8243; is for the serial service<br />
        String BTurl = &#8220;btspp://&#8221; + BT_ADDRESS + &#8220;:01;authenticate=false;encrypt=false;master=false&#8221;;<br />
        btConnection = (StreamConnection) Connector.open(BTurl);<br />
        try {<br />
          InputStream btInputStream = btConnection.openInputStream();<br />
          btOutputStream = btConnection.openOutputStream();<br />
          ///send a byte out in case other side is waiting to be prompted<br />
          send(65);<br />
          while (true) {<br />
            //read in a byte at a time, this stops for the byte, that is why we are in a thread<br />
            int input = btInputStream.read();<br />
            blueToothEvent(input);<br />
          }<br />
        }<br />
        catch (IOException e) {<br />
          println(&#8220;Stopped Listening To BlueTooth&#8221;);<br />
        }<br />
      }<br />
      catch (IOException e) {<br />
        println(&#8220;Sorry but could not connect. to &#8221; + BT_ADDRESS);<br />
      }<br />
      disconnect();<br />
    }</p>
<p>    void send(int _output){<br />
      try{<br />
        btOutputStream.write( _output);<br />
        btOutputStream.flush();<br />
      }<br />
      catch (IOException e) {<br />
        println(&#8220;Stopped Listening To BlueTooth&#8221;);<br />
      }<br />
    }</p>
<p>    void disconnect() {<br />
      try {</p>
<p>        btConnection.close();<br />
      }<br />
      catch (Exception e) {<br />
        println(&#8220;Trouble Closing Connection.&#8221;);</p>
<p>      }</p>
<p>    }</p>
<p>  }<br />
}</p>
<p>ARDUINO:</p>
<p>int analogReading;  //variable int size because adc number potentially as big as 1024</p>
<p>void setup()<br />
{<br />
   beginSerial(9600);  //set up communication back to pc<br />
   //don&#8217;t forget to press &#8220;serial monitor button&#8221;<br />
}</p>
<p>void loop()<br />
{<br />
  analogReading = analogRead(0); //can only use pins 0-5<br />
  Serial.print(analogReading,DEC);<br />
  Serial.print(44,BYTE);<br />
  analogReading = analogRead(1); //can only use pins 0-5<br />
  Serial.print(analogReading,DEC);<br />
  Serial.println(10,BYTE); //talk back to pc<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=115</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Phone Heart</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=112</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=112#comments</comments>
		<pubDate>Fri, 03 Oct 2008 15:38:00 +0000</pubDate>
		<dc:creator>Dano</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=112</guid>
		<description><![CDATA[It is kind of a kick to see your heart beat.  Polar is a company that makes lots of stuff for athletes to watch their heart beat.  The data usually goes to something like a watch and i think it is pretty hard to get your own hands on the it.  I made this example for [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/heartphone2.jpg"></a></p>
<p><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/heartphone21.jpg"></a><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/heartphone23.jpg"><img class="alignright size-medium wp-image-119" title="heartphone23" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/heartphone23-300x153.jpg" alt="" width="300" height="153" /></a>It is kind of a kick to see your heart beat.  Polar is a company that makes lots of stuff for athletes to watch their heart beat.  The data usually goes to something like a watch and i think it is pretty hard to get your own hands on the it.  I made this example for students in my <a href="http://itp.nyu.edu/blogs/restofyou/">Rest of You</a> class to be able to use their heart control somthing or just be able to see the same data in their own visualization. </p>
<p><span id="more-112"></span> </p>
<p>You can this fantastic <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8661">module</a> from Sparkfun or alternatively this cheaper <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8660">chip</a>.   If you get the fancier one, the serial output pins line up perfectly the &#8220;<a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8332">Blue Smirf</a>&#8220; bluetooth module (also from Sparkfun).  Sparkfun is making this stuff so easy I somehow feel guilty.  Anyway I wrote some code to get the readings in and show them on the cell phone.  I did the example in <a href="http://mobile.processing.org/">mobile proccessing</a> but didn&#8217;t use their library for the bluetooth connection but instead just pasted in my own class called BTThread.  To keep the code simple I wanted to avoid the whole part where one device &#8220;discovers&#8221; other devices and services.  Instead I use my laptop to find the address of the bluetooth module (it will look like &#8220;00A096179A85&#8243;) and 1 hardcoded it.  I also put some lines in there for logging the data but I commented it out because if might slow you down.   Here is the code:<br />
import java.io.IOException;<br />
import java.io.InputStream;<br />
import java.io.OutputStream;</p>
<p>import javax.microedition.io.Connector;<br />
import javax.microedition.io.StreamConnection;<br />
public class MobileHeart extends PMIDlet{<br />
  String BT_ADDRESS = &#8220;00A096179A85&#8243;;  //use your laptop to figure out the hardware address of the blue smirf.</p>
<p>  BTThread blueTooth;</p>
<p>  int xpos;<br />
  PFont font ;<br />
  int recordNum  ;<br />
  String accumulatedFromBT = &#8220;&#8221;;<br />
  String  filePrefix = &#8220;mhb&#8221;;  //distinguishes log file from other apps.</p>
<p>  int timeOfLastReading = 0;<br />
  int interval = 1000;  //how often you want to read</p>
<p>  public void setup(){<br />
    font = loadFont(&#8220;ArialMT-12.mvlw&#8221;);</p>
<p>    String[] savedPlace = loadStrings( filePrefix + &#8220;SavedPlace&#8221;);<br />
    //if (getLength(savedPlace) &gt; 0) {<br />
    // recordNum =  Integer.parseInt( savedPlace[0].trim());<br />
    //}</p>
<p>    blueTooth = new BTThread();<br />
    blueTooth.start();</p>
<p>  }</p>
<p>  public void draw(){<br />
    if (millis() &#8211; timeOfLastReading &gt; interval &amp;&amp; blueTooth != null){<br />
      blueTooth.send(71);<br />
      blueTooth.send(49);<br />
      blueTooth.send(13);<br />
      timeOfLastReading = millis();<br />
    }</p>
<p>  }<br />
  void blueToothEvent(int input){<br />
    accumulatedFromBT = accumulatedFromBT + (char) input;</p>
<p>    if (input == 13) {<br />
      println(&#8220;In From BlueTooth: &#8221; + accumulatedFromBT);<br />
      String[] parts = split(accumulatedFromBT,&#8221; &#8220;);<br />
      accumulatedFromBT = &#8220;&#8221;;  //reset accumulation<br />
      if (getLength(parts) &gt; 2) {<br />
        try {<br />
          int status1 = Integer.parseInt((parts[0].trim()));<br />
          int status2 = Integer.parseInt((parts[1].trim()));<br />
          int heart = Integer.parseInt((parts[2].trim()));<br />
          //  background(0);<br />
          fill(255, 255, 255);<br />
          rect(0,0,width,130); //clear the place where you are writing text<br />
          text (&#8220;Heart&#8221; + heart, 10,120);<br />
          /*  saveStrings( filePrefix + &#8220;Val&#8221;+recordNum,parts);<br />
           saveStrings( filePrefix + &#8220;SavedPlace&#8221;,new String[] {<br />
           String.valueOf(recordNum)                                                                                          }<br />
           );  //recorde the last place you saved<br />
           */<br />
          //recordNum++;</p>
<p>          fill(255, 0, 255);<br />
          ellipse(xpos, heart+ height/2, 2, 2);<br />
          xpos = xpos + 2;<br />
          if (xpos &gt;= width) {<br />
            xpos = 0;<br />
            background(255,0,0);<br />
          }<br />
        }<br />
        catch (NumberFormatException e) {<br />
          println(&#8220;Not a line of Numbers&#8221;);<br />
        }<br />
      }</p>
<p>    }<br />
  }</p>
<p>  int getLength(Object[] o)  { //don&#8217;t pay attention, servicing a bug in m.p.<br />
    return o.length; //ideally you could just say yourObject.length<br />
  }<br />
  class BTThread extends Thread {<br />
    StreamConnection btConnection = null;<br />
    OutputStream btOutputStream = null;<br />
    /* thread to accumulate bytes  */</p>
<p>    public void run() {<br />
      textFont(font);</p>
<p>      try {<br />
        //surrounds hardware address in bluetooth stuff. &#8220;:01&#8243; is for the serial service<br />
        String BTurl = &#8220;btspp://&#8221; + BT_ADDRESS + &#8220;:01;authenticate=false;encrypt=false;master=false&#8221;;<br />
        btConnection = (StreamConnection) Connector.open(BTurl);<br />
        try {<br />
          InputStream btInputStream = btConnection.openInputStream();<br />
          btOutputStream = btConnection.openOutputStream();<br />
          while (true) {<br />
            //read in a byte at a time, this stops for the byte, that is why we are in a thread<br />
            int input = btInputStream.read();<br />
            blueToothEvent(input);<br />
          }<br />
        }<br />
        catch (IOException e) {<br />
          println(&#8220;Stopped Listening To BlueTooth&#8221;);<br />
        }<br />
      }<br />
      catch (IOException e) {<br />
        println(&#8220;Sorry but could not connect. to &#8221; + BT_ADDRESS);<br />
      }<br />
      disconnect();<br />
    }</p>
<p>    void send(int _output){<br />
      try{<br />
        if (btOutputStream != null){<br />
          btOutputStream.write( _output);<br />
          btOutputStream.flush();<br />
        }<br />
      }<br />
      catch (IOException e) {<br />
        println(&#8220;Stopped Listening To BlueTooth&#8221;);<br />
      }<br />
    }</p>
<p>    void disconnect() {<br />
      try {</p>
<p>        btConnection.close();<br />
      }<br />
      catch (Exception e) {<br />
        println(&#8220;Trouble Closing Connection.&#8221;);</p>
<p>      }</p>
<p>    }</p>
<p>  }<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=112</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t Blink (In Progress)</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=17</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=17#comments</comments>
		<pubDate>Fri, 13 Jun 2008 19:46:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Pressure Projects]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=17</guid>
		<description><![CDATA[You look at a screen that works as a mirror reflecting your face. If you blink your eyes, a picture of me thumbing my nose at you comes up but you will never know. Just like you will never know if your refrigerator light is really off. This was done as the Thursday project in [...]]]></description>
			<content:encoded><![CDATA[<p>You look at a screen that works as a mirror reflecting your face.  If you blink your eyes, a picture of me thumbing my nose at you comes up but you will never know.  Just like you will never know if your refrigerator light is really off.  This was done as the Thursday project in the 7 projects in 7 days (5 in 5 for me, … er make that 3.5 in 5) festival at ITP.  I am hoping to get back this afternoon to finish it but don&#8217;t know if I will.</p>
<p><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/open.jpg"><img class="alignnone size-medium wp-image-18" title="open" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/open-300x225.jpg" alt="" width="206" height="154" /></a><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/shut.jpg"><img class="alignnone size-medium wp-image-19" title="shut" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/shut-300x224.jpg" alt="" width="206" height="154" /></a></p>
<p style="text-align: center;"><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/image1.jpg"><img class="alignnone size-medium wp-image-21 alignleft" style="float: left;" title="image1" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/image1-300x225.jpg" alt="" width="194" height="145" /></a></p>
<p><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/image1.jpg"><br />
</a></p>
<p>I am looking for holes in the skin color to find the eyes.  When I get back today I will segement out just the holes for the eyes.</p>
<p>Here is the code so far:</p>
<p><span id="more-17"></span></p>
<p>import java.awt.AlphaComposite;<br />
import java.awt.Color;<br />
import java.awt.Font;<br />
import java.awt.Graphics2D;<br />
import java.awt.List;<br />
import java.awt.Rectangle;<br />
import java.awt.event.KeyEvent;<br />
import java.awt.event.KeyListener;<br />
import java.awt.image.BufferedImage;<br />
import java.awt.image.Raster;<br />
import java.awt.image.WritableRaster;<br />
import java.util.ArrayList;<br />
import java.util.Arrays;</p>
<p>import blobs.Blob;<br />
import blobs.BlobFinder;<br />
import blobs.BlobInPixelSource;<br />
import blobs.BrightBlob;</p>
<p>import pFaceDetect.PFaceDetect;<br />
import processing.core.PApplet;<br />
import processing.core.PFont;<br />
import processing.core.PImage;<br />
import util.VariableAdjuster;<br />
import vxp.AxisPixelSource;<br />
import vxp.PixelSource;<br />
import java.awt.AlphaComposite;<br />
import java.awt.Color;<br />
import java.awt.Font;<br />
import java.awt.Graphics2D;<br />
import java.awt.Rectangle;<br />
import java.awt.event.KeyEvent;<br />
import java.awt.image.BufferedImage;<br />
import java.awt.image.WritableRaster;<br />
import java.util.ArrayList;<br />
import java.util.Arrays;</p>
<p>import processing.core.PApplet;<br />
import util.VariableAdjuster;<br />
import vxp.AxisPixelSource;<br />
import vxp.PixelSource;</p>
<p>import blobs.Blob;<br />
import blobs.BlobFinder;<br />
import blobs.BlobInPixelSource;<br />
import blobs.SkinBlob;</p>
<p>public class DontBlink extends PApplet {</p>
<p>PFont myFont;</p>
<p>int w = 320;</p>
<p>int h = 240;</p>
<p>Rectangle seedArea = new Rectangle(0,0,320,240);</p>
<p>FaceFinder face;<br />
PFaceDetect facecv;<br />
PixelSource ps ;</p>
<p>public void setup() {<br />
size(800, 600);</p>
<p>myFont = createFont(&#8220;Arial&#8221;, 12);<br />
ps = new AxisPixelSource(&#8220;128.122.151.189&#8243;, 320, 240, false);<br />
face = new FaceFinder(ps);<br />
facecv = new PFaceDetect(this, ps.getVideoWidth(),ps.getVideoHeight(), &#8220;haarcascade_frontalface_default.xml&#8221;);</p>
<p>}</p>
<p>public void draw() {<br />
// background(0);<br />
BufferedImage img = ps.getImage();<br />
image(new PImage(img), 0, 0, 320, 240);<br />
//facecv.findFaces(new PImage(img));<br />
//int[][] res = facecv.getFaces();<br />
//if (res.length &gt; 0) {<br />
// println(&#8220;Sendit&#8221;);<br />
//Rectangle seedArea = new Rectangle(res[0][0],res[0][1],res[0][2],res[0][3]);<br />
img= face.vxpanalyze(seedArea);<br />
image(new PImage(img), 0, 0, 320, 240);<br />
//noFill();<br />
//rect( seedArea.x,seedArea.y, seedArea.width, seedArea.height);</p>
<p>// rect(x, y, w, h);<br />
/*<br />
* for (int i = res.length &#8211; 1; i &gt; res.length &#8211; 2; i&#8211;) { int x = res[i][0]; int y = res[i][1]; int w = res[i][2]; int h = res[i][3]; rect(x, y, w, h); BufferedImage bi = video.getImage().getSubimage(x, x, w, h); new Sender(mySocket, bi); }<br />
*/<br />
//}</p>
<p>// setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.01f));</p>
<p>}</p>
<p>static public void main(String _args[]) {<br />
PApplet.main(new String[] { &#8220;DontBlink&#8221; });</p>
<p>}<br />
public void keyPressed(KeyEvent e){<br />
face.keyPressed(e);<br />
}</p>
<p>public class FaceFinder{<br />
BufferedImage myImage;</p>
<p>BufferedImage backgroundImage;</p>
<p>WritableRaster braster;</p>
<p>BufferedImage displayImage;</p>
<p>BlobFinder skinFinder = new BlobFinder(w, h);</p>
<p>VariableAdjuster variableAdjuster;</p>
<p>PixelSource ps;</p>
<p>SkinBlob19 skinBlob;</p>
<p>public int consolidationX = 5;</p>
<p>public int consolidationY = 5;</p>
<p>ArrayList&lt;Blob&gt; existingBlobs = new ArrayList&lt;Blob&gt;();</p>
<p>// ArrayList&lt;Blob&gt; oldEnoughBefore = new ArrayList&lt;Blob&gt;();<br />
public int tooSmall = 1000;</p>
<p>public FaceFinder(PixelSource _ps){<br />
backgroundImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);<br />
braster = backgroundImage.getRaster();<br />
displayImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);<br />
ps = _ps;</p>
<p>//protoBlob = new Blob19(aps);<br />
skinBlob = new SkinBlob19(_ps);</p>
<p>//seedArea = new Rectangle(0, 0, 320, 240);<br />
variableAdjuster = new VariableAdjuster(this, null, ps.getDeviceName());<br />
//variableAdjuster.addObject(protoBlob, &#8220;ProtoBlob&#8221;);<br />
variableAdjuster.addObject(skinBlob, &#8220;SkinBlob&#8221;);<br />
//variableAdjuster.addObject(bf, &#8220;BlobFinder&#8221;);<br />
variableAdjuster.addObject(skinFinder, &#8220;SkinFinder&#8221;);<br />
}<br />
public int dist(int a, int b, int c, int a1, int b1, int c1) {<br />
return (int) Math.sqrt(Math.pow(a &#8211; a1, 2) + Math.pow(b &#8211; b1, 2) + Math.pow(c &#8211; c1, 2));<br />
}</p>
<p>public void keyPressed(KeyEvent _e) {<br />
variableAdjuster.keyPressed(_e);<br />
}</p>
<p>public BufferedImage vxpanalyze(Rectangle _seedArea) {<br />
if (ps.grabFrame()) {<br />
long now = System.currentTimeMillis();<br />
myImage = ps.getImage();</p>
<p>Graphics2D myGraphics = displayImage.createGraphics();<br />
myGraphics.drawImage(myImage, 0, 0, null);<br />
skinFinder.clearDebugImage();<br />
ArrayList foundBlobs = skinFinder.findBlobs(skinBlob, true, _seedArea);<br />
foundBlobs = BlobFinder.killSmallBlobs(foundBlobs, tooSmall);<br />
skinFinder.consolidate(foundBlobs, consolidationX, consolidationY, false);<br />
BlobFinder.drawRects(Color.PINK, myGraphics, foundBlobs);<br />
skinFinder.lookForContinuity(existingBlobs, foundBlobs, true, false);</p>
<p>myGraphics.drawImage(skinFinder.getDebugImage(), 0, 0, null);<br />
myGraphics.drawImage(variableAdjuster.getImage(), 0, 0, null);</p>
<p>}<br />
return displayImage;<br />
// return myImage;<br />
}</p>
<p>public class SkinBlob19 extends BlobInPixelSource {</p>
<p>public float skinRedLower = .35f;</p>
<p>public float skinRedUpper = .55f;</p>
<p>public float skinGreenLower = .26f;</p>
<p>public float skinGreenUpper = .35f;</p>
<p>public SkinBlob19(PixelSource _ps) {<br />
super(_ps);<br />
}</p>
<p>// public Object clone(){<br />
// if (debugImage == null){<br />
// return new Skin(ps) ;<br />
// }<br />
// return new Skin(ps);<br />
// }<br />
public boolean doesPixelQualify(int[] _rgb) {<br />
int total = (_rgb[0] + _rgb[1] + _rgb[2]);<br />
float nr = (float) _rgb[0] / total;<br />
float ng = (float) _rgb[1] / total;</p>
<p>return (( nr &lt; skinRedUpper &amp;&amp; nr &gt; skinRedLower &amp;&amp; ng &lt; skinGreenUpper &amp;&amp; ng &gt; skinGreenLower));<br />
}</p>
<p>public void shiftRed(float _redShift) {<br />
skinRedUpper = skinRedUpper + _redShift;<br />
skinRedLower = skinRedLower + _redShift;<br />
}</p>
<p>public void shiftGreen(float _greenShift) {<br />
skinGreenUpper = skinGreenUpper + _greenShift;<br />
skinGreenLower = skinGreenLower + _greenShift;<br />
}</p>
<p>public float[] getRanges() {<br />
float[] a = { skinRedLower, skinRedUpper, skinGreenLower, skinGreenUpper };<br />
return a;<br />
}</p>
<p>}<br />
}</p>
<p>}</p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=17</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Face the Web</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=15</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=15#comments</comments>
		<pubDate>Thu, 12 Jun 2008 22:07:56 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Pressure Projects]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=15</guid>
		<description><![CDATA[Allows people to congregate in a layer on top of your web browser. Using a webcam attached to your computer the application grabs your face and sends it to other people looking at the same web page. Your face is displayed on other peoples&#8217; browser at the place on the page you are most interested [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/faceweb.jpg"><img class="alignnone size-medium wp-image-16" title="faceweb" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/faceweb-300x168.jpg" alt="" width="300" height="168" /></a></p>
<p>Allows people to congregate in a layer on top of your web browser.  Using a webcam attached to your computer the application grabs your face and sends it to other people looking at the same web page.  Your face is displayed on other peoples&#8217; browser at the place on the page you are most interested in  as expressed by your cursor location.  The web page becomes a substrate for gathering.  In the future I would like to degrade the resolution of  faces of people interested in things further away on the page and change to peer to peer architecture for the actual transmission of the images.   This was done as the Thursday project in the 7 projects in 7 days (5 in 5 for me, &#8230; er make that 4 in 5) festival at ITP.<span id="more-15"></span></p>
<p>Tech: OpenCV processing <a href="http://www.bryanchung.net/?page_id=251">libraries</a> for the face detection but I would probably change that. I used IP cameras for the video capture.  It also used a new <a href="http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html">capability</a> in Java 1.6 for overlaying on on other applications.  Unfortunately it only allows for a global translucency for the frame, not pixel by pixel transparency.  It does allow for not rectilinear shapes so I might change it to that.  Below is the code:</p>
<p><!--more--></p>
<p><strong>Client:</strong></p>
<p>import java.awt.*;<br />
import java.awt.image.BufferedImage;<br />
import java.io.ByteArrayInputStream;<br />
import java.io.ByteArrayOutputStream;<br />
import java.io.DataInputStream;<br />
import java.io.DataOutputStream;<br />
import java.io.IOException;<br />
import java.io.UTFDataFormatException;<br />
import java.net.Socket;<br />
import java.net.UnknownHostException;</p>
<p>import javax.swing.*;</p>
<p>import com.sun.image.codec.jpeg.ImageFormatException;<br />
import com.sun.image.codec.jpeg.JPEGCodec;<br />
import com.sun.image.codec.jpeg.JPEGEncodeParam;<br />
import com.sun.image.codec.jpeg.JPEGImageDecoder;<br />
import com.sun.image.codec.jpeg.JPEGImageEncoder;<br />
import com.sun.image.codec.jpeg.TruncatedFileException;</p>
<p>import pFaceDetect.PFaceDetect;<br />
import processing.core.PApplet;<br />
import processing.core.PImage;<br />
import processing.net.Server;<br />
import vxp.AxisPixelSource;<br />
import vxp.CaptureAxisCamera;</p>
<p>public class FaceTheWeb extends PApplet {<br />
Server myServer;</p>
<p>int endOfMessageChar = 10;</p>
<p>Socket mySocket;</p>
<p>int socketPort = 9001;</p>
<p>String ip = &#8220;localhost&#8221;;</p>
<p>AxisPixelSource video;</p>
<p>boolean reply = true;</p>
<p>static String[] args;</p>
<p>int otherx, othery;</p>
<p>PImage other;</p>
<p>int myConnectionNumber = -1;</p>
<p>PFaceDetect face;</p>
<p>// PImage img;<br />
public void setup() {<br />
size(screen.width,screen.height);<br />
setLocation(0,0);<br />
JFrame.setDefaultLookAndFeelDecorated(true);<br />
com.sun.awt.AWTUtilities.setWindowOpacity(this.frame, 0.5f);<br />
video = new AxisPixelSource(&#8220;128.122.151.189&#8243;, 320, 240, false);</p>
<p>face = new PFaceDetect(this, video.getVideoWidth(), video.getVideoHeight(), &#8220;haarcascade_frontalface_default.xml&#8221;);</p>
<p>try {<br />
mySocket = new Socket(ip, socketPort);<br />
} catch (UnknownHostException e) {<br />
println(&#8220;Could not find host address&#8221;);<br />
} catch (IOException e) {<br />
println(&#8220;Could not connect to host&#8221;);<br />
}<br />
println(&#8220;Connecting as client at &#8221; + socketPort + &#8221; on &#8221; + ip);<br />
new TeleListener(mySocket);</p>
<p>}</p>
<p>static public void main(String _args[]) {<br />
PApplet.main(new String[] { &#8220;FaceTheWeb&#8221; });</p>
<p>}</p>
<p>public void draw() {<br />
background(255,255,255,0);</p>
<p>if (other != null) {<br />
image(other, otherx, othery, other.width, other.height);<br />
}</p>
<p>}</p>
<p>public void sendPicture() {<br />
if (mySocket != null &amp;&amp; video != null) {<br />
BufferedImage img = video.getImage();</p>
<p>face.findFaces(new PImage(img));<br />
int[][] res = face.getFaces();<br />
if (res.length &gt; 0) {<br />
// println(&#8220;Sendit&#8221;);<br />
int x = res[0][0];<br />
int y = res[0][1];<br />
int w = res[0][2];<br />
int h = res[0][3];<br />
// rect(x, y, w, h);<br />
BufferedImage bi = video.getImage().getSubimage(x, y, w, h);<br />
new Sender(mySocket, bi);<br />
/*<br />
* for (int i = res.length &#8211; 1; i &gt; res.length &#8211; 2; i&#8211;) { int x = res[i][0]; int y = res[i][1]; int w = res[i][2]; int h = res[i][3]; rect(x, y, w, h); BufferedImage bi = video.getImage().getSubimage(x, x, w, h); new Sender(mySocket, bi); }<br />
*/<br />
}<br />
}</p>
<p>}</p>
<p>public void mousePressed() {<br />
sendPicture();<br />
}</p>
<p>public void incoming(PImage _img, int _connectionNumber) {<br />
// println(&#8220;INcoming&#8221;);<br />
if (_img != null) other = _img;</p>
<p>}</p>
<p>public class TeleListener extends Thread {</p>
<p>DataInputStream dis;</p>
<p>DataOutputStream dout;</p>
<p>int connectionNumber = 0;</p>
<p>TeleListener(Socket _c) {</p>
<p>try {<br />
dis = new DataInputStream(_c.getInputStream());<br />
dout = new DataOutputStream(_c.getOutputStream());<br />
} catch (IOException e) {<br />
println(&#8220;Couldn&#8217;t Connect&#8221;);<br />
}</p>
<p>start();<br />
}</p>
<p>public void run() {</p>
<p>while (true) {<br />
int size = 0;<br />
int connectionNumber = 0;</p>
<p>try {<br />
String header = null;<br />
try {</p>
<p>header = dis.readUTF();<br />
} catch (UTFDataFormatException e) {<br />
System.out.println(&#8221; UTFDataFormatException  exeption &#8220;);<br />
continue;<br />
}<br />
if (header == null) break;<br />
try {<br />
String[] messageParts = header.split(&#8220;,&#8221;);<br />
size = Integer.parseInt(messageParts[1]);<br />
otherx = Integer.parseInt(messageParts[2]);<br />
othery = Integer.parseInt(messageParts[3]);</p>
<p>} catch (RuntimeException e) {<br />
System.out.println(&#8221; RuntimeException exeption &#8220;);<br />
continue;<br />
}</p>
<p>if (size == 0) continue;</p>
<p>// make a buffer that size to accept the incoming bytes<br />
byte[] incoming = new byte[size];<br />
dis.readFully(incoming);<br />
PImage myImage = null;<br />
myImage = byteArrayToPImage(incoming);</p>
<p>incoming(myImage, connectionNumber);<br />
// println(connectionNumber + &#8221; Client got&#8221; + size);<br />
} catch (NumberFormatException e) {<br />
System.out.println(&#8220;Text to number problem.&#8221;);<br />
break;<br />
} catch (IOException e) {<br />
System.out.println(&#8220;Nothing came in.&#8221;);<br />
break;<br />
}</p>
<p>}<br />
}<br />
}</p>
<p>public class Sender extends Thread {<br />
DataOutputStream dos;</p>
<p>DataInputStream dis;</p>
<p>BufferedImage img;</p>
<p>Sender(Socket _c, BufferedImage _image) {<br />
try {<br />
dos = new DataOutputStream(_c.getOutputStream());<br />
dis = new DataInputStream(_c.getInputStream());<br />
} catch (IOException e) {<br />
println(&#8220;Couldn&#8217;t Connect&#8221;);<br />
}<br />
img = _image;<br />
start();<br />
}</p>
<p>public void run() {</p>
<p>byte[] imageInBytes = imageToByteArray(img);<br />
// tell them how many bytes to expect<br />
String outSize = String.valueOf(imageInBytes.length);<br />
String header = &#8220;enclosure,&#8221; + outSize + &#8220;,&#8221; + mouseX + &#8220;,&#8221; + mouseY;</p>
<p>try {<br />
DataOutputStream dos = new DataOutputStream(mySocket.getOutputStream());<br />
dos.writeUTF(header);<br />
dos.flush();<br />
dos.write(imageInBytes);<br />
dos.flush();<br />
} catch (IOException e) {<br />
e.printStackTrace();<br />
}</p>
<p>}</p>
<p>}</p>
<p>public byte[] imageToByteArray(BufferedImage _image) {</p>
<p>// bit if a hack to convert PImage to a Buffered Image, draw it on the buffered image<br />
// ((BufferedImage) image).getRGB(x, y, w, h, img.pixels, offset, img.width);</p>
<p>// BufferedImage bi = new BufferedImage(_image.width, _image.height, BufferedImage.TYPE_INT_RGB);</p>
<p>// bi.setRGB(0, 0, _image.width, _image.height, _image.pixels, 0, _image.width);<br />
// compress and turn into a byte array<br />
// okay just to copy and paste this method</p>
<p>ByteArrayOutputStream baOut = new ByteArrayOutputStream();<br />
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baOut);<br />
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(_image);<br />
param.setQuality(0.9f, false);<br />
encoder.setJPEGEncodeParam(param);<br />
try {<br />
encoder.encode(_image);<br />
baOut.flush();<br />
} catch (ImageFormatException e) {<br />
System.out.println(&#8220;could not  form image&#8221; + e);<br />
} catch (IOException e) {<br />
System.out.println(&#8220;could not encode image&#8221; + e);<br />
}</p>
<p>return baOut.toByteArray();<br />
}</p>
<p>public PImage byteArrayToPImage(byte[] _pic) {<br />
// decompress into a buffferedImage<br />
// okay just to copy and paste this method<br />
ByteArrayInputStream in = new ByteArrayInputStream((byte[]) _pic);<br />
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);<br />
BufferedImage snapShot = null;<br />
try {<br />
snapShot = decoder.decodeAsBufferedImage();<br />
} catch (ImageFormatException e) {<br />
System.out.println(&#8220;Could not make array into a jpeg. &#8221; + _pic.length);</p>
<p>} catch (TruncatedFileException e) {<br />
System.out.println(&#8220;Truncated File&#8221; + _pic.length);<br />
} catch (IOException e) {<br />
System.out.println(&#8220;IO Making file&#8221; + _pic.length);<br />
}</p>
<p>if (snapShot == null) return null;<br />
return new PImage(snapShot);<br />
}</p>
<p>}</p>
<p><strong>Server:</strong></p>
<p>import java.io.DataInputStream;<br />
import java.io.DataOutputStream;<br />
import java.io.IOException;<br />
import java.net.InetAddress;<br />
import java.net.ServerSocket;<br />
import java.net.Socket;<br />
import java.util.ArrayList;</p>
<p>/*<br />
* Created on Feb 7, 2005<br />
*<br />
*/</p>
<p>/**<br />
* @author Dan O&#8217;Sullivan<br />
*<br />
* Allows conections to come in and spawns thread to take care of them<br />
*/<br />
public class FaceToWebServer {<br />
int lastConnectionNumber = 0;</p>
<p>ArrayList allConnections = new ArrayList();</p>
<p>public static void main(String[] args) {<br />
new  FaceToWebServer();<br />
}</p>
<p>FaceToWebServer() {<br />
ServerSocket frontDoor;<br />
int portNum = 9001;<br />
try {<br />
frontDoor = new ServerSocket(portNum);<br />
System.out.println(&#8220;Set up a door at &#8221; + InetAddress.getLocalHost() + &#8221;  &#8221; + frontDoor.getLocalPort());<br />
while (true) {<br />
System.out.println(&#8220;Waiting for a new connection&#8221;);<br />
Socket newSocket = frontDoor.accept();// sits here and waits for // someone to knock on the door<br />
System.out.println(newSocket.getRemoteSocketAddress() + &#8221; knocked on the door and I let them in&#8221;);<br />
// farm it out immediately to another thread<br />
ServerThread newServerThread = new ServerThread(newSocket);<br />
allConnections.add(newServerThread); // add it to the list of connections<br />
newServerThread.setConnectionID(lastConnectionNumber);<br />
lastConnectionNumber++;<br />
newServerThread.start();// this calls the run method in the thread<br />
}<br />
} catch (IOException e) {<br />
System.out.println(&#8220;Had a problem making a front door&#8221; + e);<br />
}<br />
}</p>
<p>synchronized public void tellEveryone(ServerThread _me, String _header, byte[] _enclosure) {</p>
<p>for (int i = 0; i &lt; allConnections.size(); i++) {</p>
<p>ServerThread thisConnection = (ServerThread) allConnections.get(i);<br />
if (thisConnection == _me) continue;  //don&#8217;t send back to yourself<br />
//insert uniqueName into the header<br />
String outHeader = _header+ &#8220;,&#8221; + _me.getConnectionID() + &#8220;,&#8221; + thisConnection.getConnectionID() ;<br />
System.out.println(&#8220;Server Distributes &#8221; + outHeader);<br />
new ServerSenderThread(thisConnection.dout,outHeader,_enclosure);</p>
<p>}<br />
}</p>
<p>synchronized public void removeMe(ServerThread _which) {<br />
allConnections.remove(_which);</p>
<p>}</p>
<p>/**<br />
* @author Dan O&#8217;Sullivan A thread that listens text and relays it to other people Try to add and introduction that asks for their name and then preppends name to all comments Try adding functionality where you can wisper to a specific person<br />
*/<br />
public class ServerThread extends Thread {<br />
Socket mySocket;</p>
<p>DataInputStream din;</p>
<p>public DataOutputStream dout;</p>
<p>int connectionID =0;</p>
<p>int panPosition = 0;</p>
<p>boolean stillRunning = true;</p>
<p>ServerThread(Socket _socket) {<br />
mySocket = _socket;</p>
<p>// trade the standard byte input stream for a fancier one that allows for more than just bytes<br />
try {<br />
din = new DataInputStream(mySocket.getInputStream());<br />
dout = new DataOutputStream(mySocket.getOutputStream());<br />
} catch (IOException e) {<br />
System.out.println(&#8220;couldn&#8217;t get streams&#8221; + e);<br />
}<br />
}</p>
<p>public void run() {<br />
try {</p>
<p>while (stillRunning) {<br />
String header = null;<br />
byte[] enclosure = null;</p>
<p>header = din.readUTF();</p>
<p>if (header == null) {<br />
killMe();<br />
break;<br />
}</p>
<p>// protocol is type,size,who<br />
String[] headerParts = header.split(&#8220;,&#8221;);<br />
int size = Integer.parseInt(headerParts[1]);</p>
<p>enclosure = new byte[size];<br />
din.readFully(enclosure);<br />
header = headerParts[0] + &#8220;,&#8221; + headerParts[1]  + &#8220;,&#8221; + headerParts[2] + &#8220;,&#8221; + headerParts[3] ;</p>
<p>tellEveryone(this,header, enclosure);<br />
//System.out.println(&#8220;server got &#8221; + header );<br />
}<br />
} catch (IOException e) {<br />
killMe();<br />
System.out.println(&#8220;Connection Lost&#8221;);</p>
<p>}</p>
<p>}</p>
<p>public void killMe() {<br />
System.out.println(&#8220;Removing Connection&#8221;);<br />
stillRunning = false;<br />
removeMe(this);<br />
}</p>
<p>public void setConnectionID(int _cn){<br />
connectionID = _cn;<br />
}</p>
<p>public int getConnectionID(){<br />
return connectionID;<br />
}</p>
<p>}</p>
<p>/**<br />
* @author Dan O&#8217;Sullivan A thread that listens text and relays it to other people Try to add and introduction that asks for their name and then preppends name to all comments Try adding functionality where you can wisper to a specific person<br />
*/<br />
public class ServerSenderThread extends Thread {</p>
<p>DataOutputStream sendOut;<br />
byte[] sendEnclosure;<br />
String sendHeader;</p>
<p>ServerSenderThread(DataOutputStream _dout, String _header, byte[] _enclosure) {<br />
sendOut = _dout;<br />
sendHeader = _header;<br />
sendEnclosure = _enclosure;<br />
start();<br />
}</p>
<p>public void run() {<br />
try {<br />
sendOut.writeUTF(sendHeader);<br />
sendOut.flush();<br />
if (sendEnclosure != null){<br />
sendOut.write(sendEnclosure);<br />
sendOut.flush();<br />
}<br />
} catch (IOException e) {<br />
System.out.println(&#8220;Problem sending&#8221;);<br />
}</p>
<p>}</p>
<p>}<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=15</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Attention</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=13</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=13#comments</comments>
		<pubDate>Tue, 10 Jun 2008 21:55:13 +0000</pubDate>
		<dc:creator>Dano</dc:creator>
				<category><![CDATA[Pressure Projects]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=13</guid>
		<description><![CDATA[For determining the popularity of different video segments on public displays. It uses a camera and computer vision to notice how many faces are watching the screen. It takes advantage of a shortcoming of the OpenCV processing libraries for the face detection which only detect faces only at very limited angles. It it finds a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/attention.jpg"><img class="alignnone size-full wp-image-14" title="attention" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/attention.jpg" alt="" width="500" height="163" /></a></p>
<p>For determining the popularity of different video segments on public displays.  It uses a camera and computer vision to notice how many faces are watching the screen.  It takes advantage of a shortcoming of the OpenCV processing <a href="http://www.bryanchung.net/?page_id=251">libraries</a> for the face detection which only detect faces only at very limited angles.  It it finds a face you can be assured that they are facing only the screen.   Shawn Van Every created a video drop box for people to leave video to be seen on various screens around the floor.  We wanted to be able to cull a best of list from the drop box so Shawn VanEvery and I thought face tracking might be interesting.   It is currently hardwired to a particular video and only shows the &#8220;Attention Quotient&#8221; on the screen.  If I had more time, I would integrate it with a database of videos and register the attention into that database.  This was done as the Tuesday project in the 7 projects in 7 days (5 in 5 for me) festival at ITP.</p>
<p>Tech: I used IP cameras for the video capture.  Below is the code:</p>
<p><span id="more-13"></span></p>
<p>import java.awt.Color;<br />
import java.awt.Component;<br />
import java.io.File;</p>
<p>import javax.swing.JFrame;</p>
<p>import pFaceDetect.PFaceDetect;<br />
import processing.core.PApplet;<br />
import processing.core.PFont;</p>
<p>import quicktime.QTException;<br />
import quicktime.QTSession;<br />
import quicktime.app.view.MoviePlayer;<br />
import quicktime.app.view.QTFactory;<br />
import quicktime.io.OpenMovieFile;<br />
import quicktime.io.QTFile;<br />
import quicktime.std.StdQTException;<br />
import quicktime.std.movies.Movie;<br />
import vxp.CaptureAxisCamera;</p>
<p>public class VoteWithYourFace extends PApplet{</p>
<p>Movie qtMovie;<br />
MoviePlayer qtPlayer;<br />
Component qtCanvas;<br />
JFrame videoFrame ;<br />
String mediaFileName = &#8220;C:\\ALLFOLDERS\\ps3\\video\\others\\get_smart-tlr1_h.320.mov&#8221;;<br />
private CaptureAxisCamera video;<br />
private PFaceDetect face;<br />
PFont myFont;<br />
int attention ;<br />
int opportunities;<br />
static public void main(String _args[]) {<br />
PApplet.main(new String[] { &#8220;VoteWithYourFace&#8221; });<br />
}</p>
<p>public void setup(){<br />
try {<br />
QTSession.open();</p>
<p>System.out.println(&#8220;QTSession Open&#8221;);</p>
<p>} catch (QTException qte) {<br />
System.out.println(&#8220;Sorry NOT: QTSession Open&#8221;);<br />
}<br />
try {<br />
OpenMovieFile omf = OpenMovieFile.asRead(new QTFile(mediaFileName));<br />
qtMovie = Movie.fromFile(omf);<br />
} catch (Exception e) {<br />
System.out.println(&#8220;Problem opening file&#8221;);<br />
}</p>
<p>try {</p>
<p>qtPlayer = new MoviePlayer(qtMovie);<br />
qtCanvas = (QTFactory.makeQTComponent(qtMovie)).asComponent();</p>
<p>} catch (Exception e) {<br />
System.out.println(&#8220;Trouble Making Movie&#8221;);<br />
}</p>
<p>setBackground(Color.BLACK);</p>
<p>try {<br />
setSize(qtMovie.getNaturalBoundsRect().getWidth(), qtMovie.getNaturalBoundsRect().getHeight());<br />
qtMovie.setTimeValue(0);<br />
qtMovie.start();<br />
} catch (StdQTException e) {<br />
// TODO Auto-generated catch block<br />
e.printStackTrace();<br />
}<br />
videoFrame = new JFrame();</p>
<p>videoFrame.add(qtCanvas);<br />
videoFrame.setUndecorated(true);<br />
videoFrame.setSize(getWidth(), getHeight());<br />
videoFrame.setVisible(true);<br />
videoFrame.setLocation(100,100);<br />
video  = new CaptureAxisCamera(this,&#8221;128.122.151.189&#8243;,width,height,false);<br />
face = new PFaceDetect(this,width,height,&#8221;haarcascade_frontalface_default.xml&#8221;);<br />
myFont = createFont(&#8220;Arial&#8221;,24);<br />
}</p>
<p>public void draw() {<br />
background(0);<br />
video.read();<br />
face.findFaces(video);<br />
opportunities++;<br />
int [][] res = face.getFaces();<br />
attention = attention + res.length;<br />
String AQ = String.valueOf((float) attention/opportunities);<br />
AQ =  AQ.substring(0,Math.min(AQ.length(),4));</p>
<p>textFont(myFont);<br />
text(&#8220;Attention Quotient: &#8221; + AQ,10,100);<br />
//image(video,0,0);<br />
// drawFace();<br />
}</p>
<p>void drawFace() {<br />
int [][] res = face.getFaces();<br />
if (res.length&gt;0) {<br />
for (int i=0;i&lt;res.length;i++) {<br />
int x = res[i][0];<br />
int y = res[i][1];<br />
int w = res[i][2];<br />
int h = res[i][3];<br />
rect(x,y,w,h);<br />
}<br />
}<br />
}</p>
<p>}</p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=13</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trading Faces &#8211;Big Screen Edition</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=11</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=11#comments</comments>
		<pubDate>Tue, 10 Jun 2008 15:59:28 +0000</pubDate>
		<dc:creator>Dano</dc:creator>
				<category><![CDATA[Pressure Projects]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=11</guid>
		<description><![CDATA[As people stand in front of a mirror, this applications uses face detection technology to find the faces in the video and then display them with just the faces switched. Each person looks normal except they have someone elses eyes, nose and mouth. This far I go before. In this excersize I wanted it to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/switch.jpg"><img class="alignnone size-medium wp-image-12" title="switch" src="http://itp.nyu.edu/~dbo3/blog/wp-content/uploads/switch-300x124.jpg" alt="" width="300" height="124" /></a></p>
<p>As people stand in front of a mirror, this applications uses face detection technology to find the faces in the video and then display them with just the faces switched.  Each person looks normal except they have someone elses eyes, nose and mouth.  This far I go <a href="http://itp.nyu.edu/~dbo3/proj/mirror4567.htm">before</a>.  In this excersize I wanted it to work for a crowd standing in front of the large screen display at IAC, Gehry building.  This required that the faces be shared across multiple application so today I did the networking for that.  If I had more time I would add an oval alpha mask so the faces blend better.  This was done as a Monday project in the 7 projects in 7 days (5 in 5 for me) festival at ITP.</p>
<p>Tech: I used the OpenCV processing <a href="http://www.bryanchung.net/?page_id=251">libraries</a> for the face detection.  I used IP cameras for the video capture.  Below is the code:<span id="more-11"></span></p>
<p><strong>Client:</strong></p>
<p>import java.awt.Color;<br />
import java.awt.Graphics2D;<br />
import java.awt.image.BufferedImage;<br />
import java.io.ByteArrayInputStream;<br />
import java.io.ByteArrayOutputStream;<br />
import java.io.DataInputStream;<br />
import java.io.DataOutputStream;<br />
import java.io.IOException;<br />
import java.io.UTFDataFormatException;<br />
import java.net.Socket;<br />
import java.net.UnknownHostException;</p>
<p>import pFaceDetect.PFaceDetect;<br />
import processing.core.PApplet;<br />
import processing.core.PImage;<br />
import processing.net.Server;<br />
import vxp.CaptureAxisCamera;</p>
<p>import com.sun.image.codec.jpeg.ImageFormatException;<br />
import com.sun.image.codec.jpeg.JPEGCodec;<br />
import com.sun.image.codec.jpeg.JPEGEncodeParam;<br />
import com.sun.image.codec.jpeg.JPEGImageDecoder;<br />
import com.sun.image.codec.jpeg.JPEGImageEncoder;<br />
import com.sun.image.codec.jpeg.TruncatedFileException;</p>
<p>public class FaceLift extends PApplet {</p>
<p>Server myServer;</p>
<p>int endOfMessageChar = 10;</p>
<p>Socket mySocket;</p>
<p>int socketPort = 9001;</p>
<p>String ip = &#8220;localhost&#8221;;</p>
<p>CaptureAxisCamera video;</p>
<p>boolean reply = true;</p>
<p>static String[] args;</p>
<p>int otherx, othery, otherw, otherh;</p>
<p>PImage other;</p>
<p>int myConnectionNumber = -1;</p>
<p>// PImage img;</p>
<p>static public void main(String _args[]) {<br />
PApplet.main(new String[] { &#8220;FaceLift&#8221; });<br />
}</p>
<p>PFaceDetect face;</p>
<p>public void setup() {<br />
size(320, 240);<br />
video = new CaptureAxisCamera(this, &#8220;128.122.151.189&#8243;, width, height, false);</p>
<p>face = new PFaceDetect(this, width, height, &#8220;haarcascade_frontalface_default.xml&#8221;);<br />
frameRate(15);</p>
<p>noFill();<br />
try {<br />
mySocket = new Socket(ip, socketPort);<br />
} catch (UnknownHostException e) {<br />
println(&#8220;Could not find host address&#8221;);<br />
} catch (IOException e) {<br />
println(&#8220;Could not connect to host&#8221;);<br />
}<br />
println(&#8220;Connecting as client at &#8221; + socketPort + &#8221; on &#8221; + ip);<br />
new TeleListener(mySocket);</p>
<p>}</p>
<p>void drawFace() {<br />
int[][] res = face.getFaces();<br />
if (res.length &gt; 0) {<br />
for (int i = 0; i &lt; res.length; i++) {<br />
int x = res[i][0];<br />
int y = res[i][1];<br />
int w = res[i][2];<br />
int h = res[i][3];<br />
rect(x, y, w, h);<br />
}<br />
}<br />
}</p>
<p>public void draw() {<br />
background(0);<br />
video.read();<br />
//if (video.available()) {<br />
face.findFaces(video);<br />
image(video, 0, 0);<br />
drawFace();<br />
if (other != null) {</p>
<p>PImage img = createImage(otherw, otherh, ARGB);<br />
int centerx = width/2;<br />
int centery = height/2;<br />
for(int y=0; y &lt; img.height; y++) {<br />
for(int x=0; x &lt; img.width; x++) {<br />
int alpha = (int) (100*dist(x,centerx,y,centery)/width/2);<br />
img.pixels[y*otherw+x] = color(0, 90, 102, alpha);<br />
}</p>
<p>}</p>
<p>other.mask(img);<br />
/*BufferedImage oval = new BufferedImage(otherw, otherh, BufferedImage.TYPE_INT_ARGB);<br />
Graphics2D ovalGraphics = oval.createGraphics();<br />
ovalGraphics.setBackground(new Color(255, 0, 0, 0));<br />
ovalGraphics.clearRect(0, 0, otherw, otherh);<br />
ovalGraphics.setColor(new Color(255, 255, 255, 255));<br />
ovalGraphics.fillOval(0, 0, otherw, otherh);<br />
image(new PImage(oval), otherx, othery, otherw, otherh);<br />
*/<br />
image(other, otherx, othery, otherw, otherh);<br />
}<br />
//sendPicture();<br />
//}<br />
}</p>
<p>public void sendPicture() {<br />
if (mySocket != null &amp;&amp; video != null) {</p>
<p>int[][] res = face.getFaces();<br />
if (res.length &gt; 0) {<br />
//println(&#8220;Sendit&#8221;);<br />
otherx = res[0][0];</p>
<p>othery = res[0][1];<br />
otherw = res[0][2];<br />
otherh = res[0][3];<br />
// rect(x, y, w, h);<br />
BufferedImage bi = video.getImage().getSubimage(otherx, othery, otherw, otherh);<br />
new Sender(mySocket, bi);<br />
/*<br />
* for (int i = res.length &#8211; 1; i &gt; res.length &#8211; 2; i&#8211;) { int x = res[i][0]; int y = res[i][1]; int w = res[i][2]; int h = res[i][3]; rect(x, y, w, h); BufferedImage bi = video.getImage().getSubimage(x, x, w, h); new Sender(mySocket, bi); }<br />
*/<br />
}<br />
}</p>
<p>}</p>
<p>public void mousePressed() {<br />
sendPicture();<br />
}</p>
<p>public void incoming(PImage _img, int _connectionNumber) {<br />
//println(&#8220;INcoming&#8221;);<br />
if (_img != null) other = _img;</p>
<p>}</p>
<p>public class TeleListener extends Thread {</p>
<p>DataInputStream dis;</p>
<p>DataOutputStream dout;</p>
<p>int connectionNumber = 0;</p>
<p>TeleListener(Socket _c) {</p>
<p>try {<br />
dis = new DataInputStream(_c.getInputStream());<br />
dout = new DataOutputStream(_c.getOutputStream());<br />
} catch (IOException e) {<br />
println(&#8220;Couldn&#8217;t Connect&#8221;);<br />
}</p>
<p>start();<br />
}</p>
<p>public void run() {</p>
<p>while (true) {<br />
int size = 0;<br />
int connectionNumber = 0;</p>
<p>try {<br />
String header = null;<br />
try {</p>
<p>header = dis.readUTF();<br />
} catch (UTFDataFormatException e) {<br />
System.out.println(&#8221; UTFDataFormatException  exeption &#8220;);<br />
continue;<br />
}<br />
if (header == null) break;<br />
try {<br />
String[] messageParts = header.split(&#8220;,&#8221;);<br />
size = Integer.parseInt(messageParts[1]);</p>
<p>} catch (RuntimeException e) {<br />
System.out.println(&#8221; RuntimeException exeption &#8220;);<br />
continue;<br />
}</p>
<p>if (size == 0) continue;</p>
<p>// make a buffer that size to accept the incoming bytes<br />
byte[] incoming = new byte[size];<br />
dis.readFully(incoming);<br />
PImage myImage = null;<br />
myImage = byteArrayToPImage(incoming);</p>
<p>incoming(myImage, connectionNumber);<br />
//    println(connectionNumber + &#8221; Client got&#8221; + size);<br />
} catch (NumberFormatException e) {<br />
System.out.println(&#8220;Text to number problem.&#8221;);<br />
break;<br />
} catch (IOException e) {<br />
System.out.println(&#8220;Nothing came in.&#8221;);<br />
break;<br />
}</p>
<p>}<br />
}<br />
}</p>
<p>public class Sender extends Thread {<br />
DataOutputStream dos;</p>
<p>DataInputStream dis;</p>
<p>BufferedImage img;</p>
<p>Sender(Socket _c, BufferedImage _image) {<br />
try {<br />
dos = new DataOutputStream(_c.getOutputStream());<br />
dis = new DataInputStream(_c.getInputStream());<br />
} catch (IOException e) {<br />
println(&#8220;Couldn&#8217;t Connect&#8221;);<br />
}<br />
img = _image;<br />
start();<br />
}</p>
<p>public void run() {</p>
<p>byte[] imageInBytes = imageToByteArray(img);<br />
// tell them how many bytes to expect<br />
String outSize = String.valueOf(imageInBytes.length);<br />
String header = &#8220;enclosure,&#8221; + outSize;</p>
<p>try {<br />
DataOutputStream dos = new DataOutputStream(mySocket.getOutputStream());<br />
dos.writeUTF(header);<br />
dos.flush();<br />
dos.write(imageInBytes);<br />
dos.flush();<br />
} catch (IOException e) {<br />
e.printStackTrace();<br />
}</p>
<p>}</p>
<p>}</p>
<p>public byte[] imageToByteArray(BufferedImage _image) {</p>
<p>// bit if a hack to convert PImage to a Buffered Image, draw it on the buffered image<br />
// ((BufferedImage) image).getRGB(x, y, w, h, img.pixels, offset, img.width);</p>
<p>// BufferedImage bi = new BufferedImage(_image.width, _image.height, BufferedImage.TYPE_INT_RGB);</p>
<p>// bi.setRGB(0, 0, _image.width, _image.height, _image.pixels, 0, _image.width);<br />
// compress and turn into a byte array<br />
// okay just to copy and paste this method</p>
<p>ByteArrayOutputStream baOut = new ByteArrayOutputStream();<br />
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baOut);<br />
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(_image);<br />
param.setQuality(0.9f, false);<br />
encoder.setJPEGEncodeParam(param);<br />
try {<br />
encoder.encode(_image);<br />
baOut.flush();<br />
} catch (ImageFormatException e) {<br />
System.out.println(&#8220;could not  form image&#8221; + e);<br />
} catch (IOException e) {<br />
System.out.println(&#8220;could not encode image&#8221; + e);<br />
}</p>
<p>return baOut.toByteArray();<br />
}</p>
<p>public PImage byteArrayToPImage(byte[] _pic) {<br />
// decompress into a buffferedImage<br />
// okay just to copy and paste this method<br />
ByteArrayInputStream in = new ByteArrayInputStream((byte[]) _pic);<br />
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);<br />
BufferedImage snapShot = null;<br />
try {<br />
snapShot = decoder.decodeAsBufferedImage();<br />
} catch (ImageFormatException e) {<br />
System.out.println(&#8220;Could not make array into a jpeg. &#8221; + _pic.length);</p>
<p>} catch (TruncatedFileException e) {<br />
System.out.println(&#8220;Truncated File&#8221; + _pic.length);<br />
} catch (IOException e) {<br />
System.out.println(&#8220;IO Making file&#8221; + _pic.length);<br />
}</p>
<p>if (snapShot == null) return null;<br />
return new PImage(snapShot);<br />
}</p>
<p>void getParams() {<br />
if (args != null) { // running as an application<br />
if (args.length &gt; 0) socketPort = Integer.parseInt(args[0]);<br />
if (args.length &gt; 1) {<br />
ip = args[1];</p>
<p>}<br />
} else { // running as an applet</p>
<p>String isItThere = getParameter(&#8220;socketPort&#8221;);<br />
if (isItThere != null) socketPort = Integer.parseInt(isItThere);<br />
isItThere = getParameter(&#8220;ip&#8221;);<br />
if (isItThere != null) ip = isItThere;<br />
}<br />
}</p>
<p>}</p>
<p><strong>Server:</strong></p>
<p>import java.io.DataInputStream;<br />
import java.io.DataOutputStream;<br />
import java.io.IOException;<br />
import java.net.InetAddress;<br />
import java.net.ServerSocket;<br />
import java.net.Socket;<br />
import java.util.ArrayList;</p>
<p>/**<br />
* @author Dan O&#8217;Sullivan<br />
*<br />
* Allows conections to come in and spawns thread to take care of them<br />
*/<br />
public class FaceServer {<br />
int lastConnectionNumber = 0;</p>
<p>ArrayList allConnections = new ArrayList();</p>
<p>public static void main(String[] args) {<br />
new FaceServer();<br />
}</p>
<p>FaceServer() {<br />
ServerSocket frontDoor;<br />
int portNum = 9001;<br />
try {<br />
frontDoor = new ServerSocket(portNum);<br />
System.out.println(&#8220;Set up a door at &#8221; + InetAddress.getLocalHost() + &#8221;  &#8221; + frontDoor.getLocalPort());<br />
while (true) {<br />
System.out.println(&#8220;Waiting for a new connection&#8221;);<br />
Socket newSocket = frontDoor.accept();// sits here and waits for // someone to knock on the door<br />
System.out.println(newSocket.getRemoteSocketAddress() + &#8221; knocked on the door and I let them in&#8221;);<br />
// farm it out immediately to another thread<br />
ServerThread newServerThread = new ServerThread(newSocket);<br />
allConnections.add(newServerThread); // add it to the list of connections<br />
newServerThread.setConnectionID(lastConnectionNumber);<br />
lastConnectionNumber++;<br />
newServerThread.start();// this calls the run method in the thread<br />
}<br />
} catch (IOException e) {<br />
System.out.println(&#8220;Had a problem making a front door&#8221; + e);<br />
}<br />
}</p>
<p>synchronized public void tellNextPerson(ServerThread _me, String _header, byte[] _enclosure) {<br />
ServerThread nextPerson = null;</p>
<p>for (int i = 0; i &lt; allConnections.size(); i++) {</p>
<p>ServerThread thisConnection = (ServerThread) allConnections.get(i);<br />
if (thisConnection == _me) { //don&#8217;t send back to yourself<br />
int nextIndex = i+1;<br />
if (nextIndex &gt;= allConnections.size()) nextIndex = 0;<br />
nextPerson = (ServerThread) allConnections.get(nextIndex);<br />
String outHeader = _header;<br />
//    System.out.println(&#8220;Server Distributes &#8221; + outHeader);<br />
new ServerSenderThread(nextPerson.dout,outHeader,_enclosure);<br />
break;<br />
}<br />
}</p>
<p>}</p>
<p>synchronized public void removeMe(ServerThread _which) {<br />
allConnections.remove(_which);</p>
<p>}</p>
<p>/**<br />
* @author Dan O&#8217;Sullivan A thread that listens text and relays it to other people Try to add and introduction that asks for their name and then preppends name to all comments Try adding functionality where you can wisper to a specific person<br />
*/<br />
public class ServerThread extends Thread {<br />
Socket mySocket;</p>
<p>DataInputStream din;</p>
<p>public DataOutputStream dout;</p>
<p>int connectionID =0;</p>
<p>int panPosition = 0;</p>
<p>boolean stillRunning = true;</p>
<p>ServerThread(Socket _socket) {<br />
mySocket = _socket;</p>
<p>// trade the standard byte input stream for a fancier one that allows for more than just bytes<br />
try {<br />
din = new DataInputStream(mySocket.getInputStream());<br />
dout = new DataOutputStream(mySocket.getOutputStream());<br />
} catch (IOException e) {<br />
System.out.println(&#8220;couldn&#8217;t get streams&#8221; + e);<br />
}<br />
}</p>
<p>public void run() {<br />
try {</p>
<p>while (stillRunning) {<br />
String header = null;<br />
byte[] enclosure = null;</p>
<p>header = din.readUTF();</p>
<p>if (header == null) {<br />
killMe();<br />
break;<br />
}</p>
<p>// protocol is type,size,who<br />
String[] headerParts = header.split(&#8220;,&#8221;);<br />
int size = Integer.parseInt(headerParts[1]);</p>
<p>enclosure = new byte[size];<br />
din.readFully(enclosure);<br />
header = headerParts[0] + &#8220;,&#8221; + headerParts[1]  ;</p>
<p>tellNextPerson(this,header, enclosure);<br />
//System.out.println(&#8220;server got &#8221; + header );<br />
}<br />
} catch (IOException e) {<br />
killMe();<br />
System.out.println(&#8220;Connection Lost&#8221;);</p>
<p>}</p>
<p>}</p>
<p>public void killMe() {<br />
System.out.println(&#8220;Removing Connection&#8221;);<br />
stillRunning = false;<br />
removeMe(this);<br />
}</p>
<p>public void setConnectionID(int _cn){<br />
connectionID = _cn;<br />
}</p>
<p>public int getConnectionID(){<br />
return connectionID;<br />
}</p>
<p>}</p>
<p>/**<br />
* @author Dan O&#8217;Sullivan A thread that listens text and relays it to other people Try to add and introduction that asks for their name and then preppends name to all comments Try adding functionality where you can wisper to a specific person<br />
*/<br />
public class ServerSenderThread extends Thread {</p>
<p>DataOutputStream sendOut;<br />
byte[] sendEnclosure;<br />
String sendHeader;</p>
<p>ServerSenderThread(DataOutputStream _dout, String _header, byte[] _enclosure) {<br />
sendOut = _dout;<br />
sendHeader = _header;<br />
sendEnclosure = _enclosure;<br />
start();<br />
}</p>
<p>public void run() {<br />
try {<br />
sendOut.writeUTF(sendHeader);<br />
sendOut.flush();<br />
if (sendEnclosure != null){<br />
sendOut.write(sendEnclosure);<br />
sendOut.flush();<br />
}<br />
} catch (IOException e) {<br />
System.out.println(&#8220;Problem sending&#8221;);<br />
}</p>
<p>}</p>
<p>}<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=11</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>First Web Browsings Turn Up YORB</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=123</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=123#comments</comments>
		<pubDate>Wed, 23 Jan 2008 20:40:14 +0000</pubDate>
		<dc:creator></dc:creator>
				<category><![CDATA[Television]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=123</guid>
		<description><![CDATA[This historical document shows that our YORB figured prominently in the very earliest Web browsing: Screen shot of Tim Berners-Lee&#8217;s browser editor as developed in 1991-92. This was a true browser editor for the first version of HTML and ran on a NeXT workstation. Implemented in Objective-C, it, made it easy to create, view and [...]]]></description>
			<content:encoded><![CDATA[<dl>
<dt><a href="http://www.w3.org/MarkUp/historical">This</a> historical document shows that our <a href="http://itp.nyu.edu/~dbo3/blog/?p=46">YORB</a> figured prominently in the very earliest Web browsing:</dt>
<dt> </dt>
<dt><a href="http://www.w3.org/MarkUp/tims_editor">Screen shot of Tim Berners-Lee&#8217;s browser   editor</a> as developed in 1991-92. This was a true browser editor for the first version of HTML and ran       on a NeXT workstation. Implemented in Objective-C, it, made it easy to       create, view and edit web documents. Adding a new hypertext link was a       breeze!</dt>
<p><img class="alignnone" src="http://itp.nyu.edu/~dbo3/FirstHTML.jpg" alt="" /></p>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=123</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Graffiti Wall</title>
		<link>http://itp.nyu.edu/~dbo3/blog/?p=91</link>
		<comments>http://itp.nyu.edu/~dbo3/blog/?p=91#comments</comments>
		<pubDate>Sun, 15 Jul 2007 20:26:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Displays]]></category>

		<guid isPermaLink="false">http://itp.nyu.edu/~dbo3/blog/?p=91</guid>
		<description><![CDATA[This is a ten foot video screen on the wall a the Liberty Science Center that allow visitors to spray virtual graffiti using light emitting spray cans. Utube Video. I worked with Tom Igoe, Stephen Lewis, and Joseph O&#8217;Connell to develop this. I worked mostly on the video tracking software.]]></description>
			<content:encoded><![CDATA[<p>This is a ten foot video screen on the wall a the <a href="http://www.lsc.org/">Liberty Science Center</a> that allow visitors to spray virtual graffiti using light emitting spray cans. <a href="http://www.youtube.com/watch?v=t3TMZanUWQk">Utube Video.</a></p>
<p>I worked with Tom Igoe, Stephen Lewis, and Joseph O&#8217;Connell to develop this.  I worked mostly on the video tracking software.</p>
<p><strong class="Sub-sub-sub-header"><img style="padding: 5px; margin-right: 5px;" src="http://www.lsc.org/content/image/grafwall.jpg" alt="" width="193" height="128" align="left" /></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://itp.nyu.edu/~dbo3/blog/?feed=rss2&#038;p=91</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
