ProcessingでVideoChat(DatagramSocket)

中西研のB4関口です。

今回もProcessingネタになってしまうのですが、今回はProcessingを使ったビデオチャットを実装したいと思います。
方針としては、画像をバイト配列に変換して、データグラム通信で別のPCへ送ってあげる感じにします。今回はわかりやすさのために、スレッドとか使いません。

さくっとまずはソースを乗せてしまいます。

[java]
import processing.video.*;
import java.awt.image.*;
import java.awt.*;
import javax.imageio.*;
import java.net.DatagramPacket;

InetSocketAddress remoteAddress;
DatagramPacket sendPacket;
DatagramPacket receivePacket;
DatagramSocket receiveSocket;

Capture capture;

//送信するバイト配列
byte[] sendBytes;
//受信するバイト配列を格納する箱
byte[] receivedBytes = new byte[300000];

void setup() {
size(600,480);

capture = new Capture(this,640,480);

try {
//受信ポート
receiveSocket = new DatagramSocket(5101);
}
catch(SocketException e) {
}
//受信用パケット
receivePacket = new DatagramPacket(receivedBytes,receivedBytes.length);
//送り先
remoteAddress = new InetSocketAddress(“localhost”,5100);
try{
receiveSocket.setSoTimeout(1000);
}catch(SocketException e){
}
}

void draw() {
capture.read();
/* ここから受信 */

println(receiveSocket.isBound());
try {
receiveSocket.receive(receivePacket);
}
catch(IOException e) {
}

Image awtImage = Toolkit.getDefaultToolkit().createImage(receivedBytes);
PImage receiveImage = loadImageMT(awtImage);
/* 受信終了 */

/* ここから送信 */
//バッファーイメージに変換
BufferedImage bfImage = (BufferedImage)(capture.getImage());
//ストリームの準備
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedOutputStream os = new BufferedOutputStream(bos);

try {
bfImage.flush();
ImageIO.write(bfImage,”jpg”,os);
os.flush();
os.close();
}
catch(IOException e) {
}
sendBytes = bos.toByteArray();
try {
sendPacket = new DatagramPacket(sendBytes, sendBytes.length, remoteAddress);
try{
new DatagramSocket().send(sendPacket);
} catch(IOException e){
}
println(“bufferImageSended:”+sendBytes.length+” bytes #2″);
}
catch(SocketException e) {
}
/* 送信終了 */

//描画
image(receiveImage,0,0);
image(capture,width-width/4,height-height/4,capture.width/4,capture.height/4);
}

[/java]

横着して、catchではなにもしません。

setup()

具体的にsetup()内について見ていきます。
[java]
receiveSocket = new DatagramSocket(5101);
receivePacket = new DatagramPacket(buf,buf.length);
[/java]
ここで、受信ソケットのポートの設定をします(適当に5101番)。今回は、localhost内では2つアプリを起動することになるのですが、受信と送信ポートを互い違いにしないと動かないので注意です。(別のIPが振られてるところに飛ばすなら、全く同じアプリを起動させれば通信するはず)
その下で受信したデータをどこに格納するかを指定します。予め用意しておいたbyte[]を渡すと、受信するたびにそこに値が入っていきます。

[java]
remoteAddress = new InetSocketAddress(“localhost”,5100);
[/java]
ここで、送信先とポートを設定します。今回はlocalhostですが、普通にIPでも大丈夫です。

[java]
receiveSocket.setSoTimeout(1000);
[/java]
最後に受信のタイムアウトを設定します。今回は1000ミリ秒=1秒をタイムアウト時間に設定しました。これを指定してあげないと、受信データが来ない場合に永遠に待ち続けてしまうので、適当な値を指定してあげましょう。

draw()

次に描画部分です。まずは受信部。
[java]
try {
receiveSocket.receive(receivePacket);
}
catch(IOException e) {
}
Image awtImage = Toolkit.getDefaultToolkit().createImage(receivedBytes);
PImage receiveImage = loadImageMT(awtImage);
[/java]
凄く簡単ですね。receiveメソッドを呼んであげれば、予め設定しておいたbyte[]にバイト配列が格納されます。ので、それをまずImageにしてあげて、さらにそれをPImageに変換してます。

次は送信部です。
[java]
//バッファーイメージに変換
BufferedImage bfImage = (BufferedImage)(capture.getImage());
//ストリームの準備
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedOutputStream os = new BufferedOutputStream(bos);
[/java]
まず、キャプチャ画像をBufferedImageにしてあげて、ストリームの準備をします。
[java]
try {
bfImage.flush();
ImageIO.write(bfImage,”jpg”,os);
os.flush();
os.close();
}
catch(IOException e) {
}
sendBytes = bos.toByteArray();
try {
sendPacket = new DatagramPacket(sendBytes, sendBytes.length, remoteAddress);
try{
new DatagramSocket().send(sendPacket);
} catch(IOException e){
}
println(“bufferImageSended:”+sendBytes.length+” bytes #2″);
}
catch(SocketException e) {
}
[/java]

次にImageIOを使ってjpgに変換します。そしてストリームに流し込んで、byteArrayにしてあげます。
DatagramPacketにbyte配列と宛先情報を渡して、それをDatagramSocket.send()すると送られます。
わぁ、簡単。

という感じで、Processingで簡単なビデオチャットが出来ます。


夜景星座 がケータイ未来コンテストにて優秀賞を受賞しました

今年も六本木ヒルズでORFがありました。中西研は今年はCityCompiler、夜景星座、MailTraveler の展示を行いました。

“夜景星座 がケータイ未来コンテストにて優秀賞を受賞しました” の続きを読む

“Visual Note Taking”

こんにちは石井です。

「シンキングプロセスデザイン」で勧められていた、紙に思考の過程を書きつつ考える【ビジュアルシンキング】に関連して面白いものを見つけたので紹介します。

“Visual Note Taking / Sketchnotes ” presentation by Eva-Lotta Lamm (from slideshare)

上のリンク先はいろいろな人のプレゼンテーション用スライドが公開されている「slideshare」というサイトにたまたまあった、WebデザイナーのEva-Lotta Lammさんのスライドです。彼女はここで”Visual Note Taking”の面白さについて沢山の例を交えつつ紹介しています。

sketch by Da vincisketch

(Visual Note Takingの例:左=レオナルド・ダ・ダヴィンチによるスケッチ、右=Eva-Lottaさんによるスケッチ)

残念ながらスライドにはメモやスピーチは含まれていないので何となくの雰囲気を感じとるしかできないのですが、まず”Visual Note Taking”とは何かということから始まり、かの有名なダヴィンチのスケッチから最近のスケッチまで様々なノートを紹介しています。どのノートも一癖ある面白いものばかりでそのクオリティには驚かされるばかりです。

Visual Note Takingとはその名のとおり視覚的で直感的に捉えられるノートのとり方なのですが、このプレゼンテーションでは次に具体的なやり方について掲載されています。情報に階層をつけたり同じ要素をブロックでまとめたりするほか、タイムラインの流れに従って書いて情報を整理する方法などを紹介しています。さらに「楽しいのが一番!」と記す彼女は楽しいノートを作るために色をつけたりフレームや矢印の形を変え、文字のフォントまで変えているそうです。

中で紹介されるノートがあまりにも完成度が高いので、思考の過程としてのスケッチではなく思考の結果としてのスケッチになっている気もしますが、彼女のように楽しく工夫して思考や情報を視覚的にアウトプットできれば、それを後から見返すのも楽しくなりそうですね。

このような”Visual Note Taking”のやり方を高校時代にしていたら、毎回寝ていた古典や化学も楽しく勉強できたのかもしれません。
※スケッチの写真をもっと見てみたい方は、Flickrで「Sketchnote」などと検索してみるといろいろ出てくると思います。

夜景星座 その2

こんにちは。秋学期から新研究会に新規参加させていただいております井上と申します。
片倉さん不調のため、一週間の間が空いてしまいましたがご了承を。

前の記事で紹介された「夜景星座」アプリですが今回、私がスプラッシュ画面等々のデザインをさせて頂きました。
こちらです。

アプリの画面を描くのが初めて&パースを取るのが苦手(!)
なので拙い部分がありますが、スタイリッシュな感じは出たかなと思います。
イラストが趣味だったので、こういう所で多少なりお手伝いが出来たのは光栄でした。
次回は大森さんか、同じく新規の石井さんのどちらかが担当です。宜しくお願いいたします。

夜景星座

こんにちは、竹内です。

いま中西研のシンボル的存在の西牟田先生(現・藤田研)のアイデアである夜景星座というアプリケーションの実装を行っています。

先人達が光の点に関係性を見いだし、人や動物に例え、ストーリーを作っていったように街の光の点で思い思いの形を描く。それが夜景星座です。「夜景星座」という名前がそもそも素敵ですね。さすがです。

画像が夜景でないだけに、凄まじくアプリケーションの雰囲気が伝わらないと思うのですが、実装が完了したら画像を更新します。

技術的にはそう真新しいことも難しいこともやっていなく、純粋に見せ方が重要になるアプリケーションなので、作っている過程で非常に勉強になります。

リリースもする予定なので乞うご期待!

次は中西研のエース長野くんがブログを書いてくれるのでそれもお楽しみに!

コマだれ?を作りました

中西研の北原です。

先日SFCの秋学期が始まるタイミングで コマだれ? というサービスを作りました。これは、SFCの各コマの授業に今誰が興味を持っているかということを twitter を使って共有する仕組みになっており、UI を iphone に最適化したものです。
“コマだれ?を作りました” の続きを読む

2010年度秋学期

Faculty

中西 泰人

所属
環境情報学部 准教授
ウェブ
http://web.sfc.keio.ac.jp/~naka/

Second year in Master’s (M2)

大森 拓郎

所属
政策・メディア研究科修士課程 2年
ウェブ
http://web.sfc.keio.ac.jp/~ohmori/

First year in Master’s (M1)

北原 壮

所属
政策・メディア研究科修士課程 1年
ウェブ
http://web.sfc.keio.ac.jp/~soh335/

Senior(B4)

関口 厚次

所属
環境情報学部 4年
ウェブ
http://web.sfc.keio.ac.jp/~t07412ks/

Junior (B3)

竹内 祐太

所属
総合政策学部 3年
ウェブ
http://web.sfc.keio.ac.jp/~s08475yt/

片倉 弘貴

所属
総合政策学部 3年
ウェブ
http://web.sfc.keio.ac.jp/~s08232hk/

井上 佳美

所属
環境情報学部 3年
ウェブ
http://web.sfc.keio.ac.jp/~t08121yi/

石井 千賀

所属
環境情報学部 3年
ウェブ
http://web.sfc.keio.ac.jp/~t08057ci/

Freshman(B1)

長野 誠一郎

所属
総合政策学部 1年
ウェブ
http://web.sfc.keio.ac.jp/~s10602sn/

OB / OG

三浦稔隆

加藤 貴之

北口 真麻

粕谷 貴司

木原 祐哉(農工大)

清水 理佳(農工大)

金 駿亨(農工大)

松田 幸大(農工大)

井上 大亮(農工大)

主な就職先

  • ゴールドマン・サックス
  • ソニー
  • 竹中工務店
  • 日本ヒューレット・パッカード
  • 富士ゼロックス
  • 本田技研
  • 三井情報システム
    • (五十音順)

Laser Tag 2.0 でのSnowLeopardの問題を解決しました

中西研の北原です。

Graffiti Research Lab » L.A.S.E.R. Tag で紹介されているLaser Tagというレーザポインタでプロジェクターが投影している先に落書きが出来るアプリケーションがあります。しかし、このLaserTagが作られてからSnowLeopardにバージョンアップしたり、LaserTagが依存しているOpenFrameworksが大幅に変わるなどでSnowLeopardでカメラを使った最にクラッシュしてしまう問題がありました。

Theodore Watson – Laser Tag 2.0 – How To – Download and Source Code のコメントに紹介されていたSnowLeopardの修正版の挙動も本家と少し違うように感じられたので修正したものを

http://web.sfc.keio.ac.jp/~soh335/download/LaserTag2002SnowLeopard.zip

にアップロードしました。

変更点としては、OpenFrameworksのバージョン、0.61を利用しつつ同胞されてるOpenCVやXMLを扱うアドオンがもとのLaserTagの時と大分変わってしまっているので、0.61で動くように昔のアドオンを変更して利用するというふうにしました。

第一回XD対抗フットサル大会

中西研の関口です。

6月20日に、XDの研究室(+熊坂研)が集まり、フットサル大会を企画、開催しました。
今回は、中西研の他に、脇田研・山中研・坂井研・熊坂研の4チームが参加して下さり、非常に楽しい時間を過ごすことができました。本当にありがとうございます。

さてさて、そのフットサルですが、我が中西研は、日頃の運動不足を露呈してしまいました。
先生

フットサル

総当たりで試合をした結果、優勝は坂井研でした。商品はありませんが、おめでとうございます。

XD問わず、SFCの研究室の垣根を超えたこういった活動を今後もやっていきたいですね。

次は、フットサルやバスケットボールなどもしていきたいと思います。
集合

(今回の写真は、脇田研の方々に頂きました。ありがとう!)

Processingで射影変換(ホモグラフィ)

中西研の関口です。4年生になりました。気づいたら22歳。最近、疲れが抜けません。

さて、L.A.S.E.R. Tagをいじる機会があり、現在、P5用に移植してる真っ最中です。その中で重要な機能であるキャリブレーションの実装について今回はメモ程度に残しておきます。

L.A.S.E.R. Tagでは、読み込んだカメラ画像に対しキャリブレーションを施して正確にポインタと投影面が重なるように設定が可能となっています。これによって、斜めからカメラで落書き面を捉えても、正確に落書きすることが可能となっているんですね。

今回は、これとおんなじようなことを、Processingでやろうというわけです。

多分、L.A.S.E.R. TagではOpenCVを使ってキャリブレーションしてる気がするのですが、ProcessingにはOpenCVのライブラリがあるのですが、キャリブレーションする機能は使えないようだったので、結局頑張って計算することにしました。

そもそも、こういった平面の変換は射影変換と呼ばれていて、任意の4点が定まれば、一意にパラメータが定めることができます。(詳しくは、http://www.teu.ac.jp/clab/kondo/research/cadcgtext/Chap5/Chap503.html

ということで、キャプチャした画像から任意の4点を選択し、そこからパラメータを計算して表示すればなんとなくOKっぽいです。パラメータの計算は連立方程式をとけば出てきます。
homographyMatrix
ただ、あんまりProcessingにないライブラリやらを使いたくなかったので、今回はMatrixを使わずに計算することにしました。この際、AS3で同じことをしている人を発見したので、大いにパクリました。というかむしろ、AS3をP5に移植したといって過言ではないです。(参考:Homography | HIDIHO!

ということで、ソースコードです。

[java]
import JMyron.*;
JMyron jmyron;

PImage capture;
PImage convert;
boolean dragged = false;
int selector = 0;
final static int CAP_WIDTH = 320;
final static int CAP_HEIGHT = 240;
Point[] points = {
  new Point(),new Point(),new Point(),new Point()};

void setup(){
  size(CAP_WIDTH*3,CAP_HEIGHT);
  jmyron = new JMyron();
  jmyron.start(CAP_WIDTH,CAP_HEIGHT);  
  capture = new PImage(CAP_WIDTH,CAP_HEIGHT);
  convert = new PImage(CAP_WIDTH,CAP_HEIGHT);
  points[0].setPoint(0,0);
  points[1].setPoint(320,0);
  points[2].setPoint(320,240);
  points[3].setPoint(0,240);
}
void mousePressed(){
  if(dragged == false){
    for(int i=0; i < 4; i++){
      if(points[i].x -10 < mouseX && points[i].x + 10>mouseX){
        if(points[i].y -10 < mouseY && points[i].y + 10>mouseY){
          dragged = true;
          selector = i;
        }
      } 
    } 
  }
}
void mouseDragged(){
  if(dragged){
    if(mouseX > 0 && mouseX < CAP_WIDTH){
      points[selector].setPoint(mouseX,points[selector].y);
    }
    if(mouseY > 0 && mouseY < CAP_HEIGHT){
      points[selector].setPoint(points[selector].x,mouseY);

    }
  }
}
void mouseReleased(){
  dragged = false; 
}
void draw(){

  jmyron.update();
  int[] jImage = jmyron.image();
  capture.loadPixels();
  for(int i=0;i < capture.width*capture.height; i++){
    capture.pixels[i] = jImage[i]; 
  }
  capture.updatePixels();
  image(capture,0,0);
  ellipseMode(CENTER);
  noFill();
  strokeWeight(1);
  for(int i=0; i < 4; i++){
    stroke(255*(i%2),64*(i%4),0);

    ellipse(points[i].x,points[i].y,10,10);
    line(points[i%4].x,points[i%4].y,points[(i+1)%4].x,points[(i+1)%4].y);
  }
  convert = setTransform(capture,CAP_WIDTH,CAP_HEIGHT,points[0],points[1],points[2],points[3]);
  image(convert,CAP_WIDTH,0);

}
PImage setTransform(PImage pimg,
int destWidth, int destHeight,
Point p0, Point p1,
Point p2, Point p3){
  if ( p0 == null || p1 == null || p2 == null || p3 == null ) return null;
  float[] system = new float[8];
  system = getSystem(p0,p1,p2,p3);
  PImage target = new PImage(destWidth,destHeight);

  int i,j,x,y,u,v;
  Point p;

  for(i = 0; i

processingのcaptureを使えばいいんですが、ちょっと都合上JMyronを使わせて頂きました。と言っても、Captureでも特に問題はありません。その場合は、captureをPImageからCaptureに変えればすんなり動く気がします。

実行結果はこんな感じです。

homography

このように、ポスターが長方形ぴったりに収まるように表示されるようになりました。

これで、カメラの位置に関係なく色々することができますね!

それでわ。