Kinectã§ãªã¢ã«ã¿ã¤ã ãããçµµåç»
ãä¹
ãã¶ãã«Processingã¨Kinectã§åç»ã¤ãã£ã¦ã¿ã¾ããã
ãã£ããã¯ãレトロゲームキャラが現実に現れたらこんな感じ? 「ドット絵×現実」アートãã¨ããã®ãè¦ã¦ããããã¯ãªããªãããæãã ãªãããï¼ã§ãããã£ã¦ä»ã¾ã§ãã£ãããã¨ãããã¨ããããçµã¿åãããã°ãªã¢ã«ã¿ã¤ã ã«äººãèªèãã¦å®åèæ¯ã«ãããçµµãçæãããã¨ãã§ãããã ãªãã¨æããã£ã¦ã¿ãããæã£ãããç°¡åã«ã§ããã®ã§å
¬éãã¦ã¿ã¾ãã
ãå®æ度ã¯ãããªãã§ããå³å´ã§æ´ãç©ããã¦ããã®ã¯ç§ã®å¦»ã§ãã
ããã£ã¦ãããã¨ã¯ç¹ã«é£ãããã¨ã¯ãªãã¦ãä»ã¾ã§ãã£ããKinectとProcessingで光学迷彩ごっこをしてみたãã¨ããとびだせどうぶつの森のマイデザイン補助ツールをProcessingでつくるãã¨ãã®çµã¿åããã§å®ç¾ãã¦ãã¾ãã
ããããã£ãä»ã¾ã§ãã£ããã¨ã®ç©ã¿éãã§æ°ãããã¨ãç°¡åã«ã§ããã¨ããã®ã¯ã¡ãã£ã¨è¯ãæãã§ããã
é¢é£è¨äº
ãMac+Kinect+Processingで遊んでみる - karaage. [からあげ]ã
ãKinectとProcessingで光学迷彩ごっこをしてみた - karaage. [からあげ]ã
ãとびだせどうぶつの森のマイデザイン補助ツールをProcessingでつくる - karaage. [からあげ]ã
åèãµã¤ã
ãhttp://learning.codasign.com/index.php?title=Using_the_Kinect_with_Processingã
ãhttp://weed.cocolog-nifty.com/wzero3es/2012/02/120202-processi.htmlã
ãã½ã¼ã¹ã³ã¼ããè¦ãã人ãåããã¨ããã£ã¦ã¿ãã人ã¯ç¶ããèªãã§ã¿ã¦ä¸ããã
ã½ã¼ã¹ã³ã¼ã
ã使ãæ¹ã¯ãå®è¡ããã°åç»ãåæã«çæããã¾ããã»ã©ããã¨ããã§ã¹ãã¼ã¹ãã¼ãæ¼ãã¨ãããã°ã©ã ã¨åããã©ã«ãã«åç»ãä½ããã¾ãã
import hypermedia.video.*; import processing.video.*; int fps = 30; OpenCV opencv; MovieMaker mm; import SimpleOpenNI.*; SimpleOpenNI context; final int n_pallet = 159; final int max_color = 15; final int size_x = 64; final int size_y = 48; final int scale = 10; //final int size_x = 32; //final int size_y = 24; //final int scale = 20; int CountColor(int[] pallet, int n) { int cont = 0; int []pallet_cnt = new int[n]; for (int i=0; i < n; i++) { pallet_cnt[i] = 0; for (int j= 0; j < size_x*size_y; j++) { if (pallet[j] == i) { pallet_cnt[i]++; } } } for (int i=0; i < n; i++) { if (pallet_cnt[i] > 0) { cont++; } } return cont; } float [] pallet_r = { 255, 255, 239, 255, 255, 189, 206, 156, 82, 255, 255, 222, 255, 255, 206, 189, 189, 140, 222, 255, 222, 255, 255, 189, 222, 189, 99, 255, 255, 255, 255, 255, 222, 189, 156, 140, 255, 239, 206, 189, 206, 156, 140, 82, 49, 255, 255, 222, 255, 255, 140, 189, 140, 82, 222, 206, 115, 173, 156, 115, 82, 49, 33, 255, 255, 222, 255, 255, 206, 156, 140, 82, 222, 189, 99, 156, 99, 82, 66, 33, 33, 189, 140, 49, 49, 0, 49, 0, 16, 0, 156, 99, 33, 66, 0, 82, 33, 16, 0, 222, 206, 140, 173, 140, 173, 99, 82, 49, 189, 115, 49, 99, 16, 66, 33, 0, 0, 173, 82, 0, 82, 0, 66, 0, 0, 0, 206, 173, 49, 82, 0, 115, 0, 0, 0, 173, 115, 99, 0, 33, 82, 0, 0, 33, 255, 239, 222, 206, 189, 173, 156, 140, 115, 99, 82, 66, 49, 33, 0 }; float [] pallet_g = { 239, 154, 85, 101, 0, 69, 0, 0, 32, 186, 117, 48, 85, 0, 101, 69, 0, 32, 207, 207, 101, 170, 101, 138, 69, 69, 48, 239, 223, 207, 186, 170, 138, 101, 85, 69, 207, 138, 101, 138, 0, 101, 0, 0, 0, 186, 154, 32, 85, 0, 85, 0, 0, 0, 186, 170, 69, 117, 48, 48, 32, 16, 16, 255, 255, 223, 255, 223, 170, 154, 117, 85, 186, 154, 48, 85, 0, 69, 0, 0, 16, 186, 154, 48, 85, 0, 48, 0, 16, 0, 239, 207, 101, 170, 138, 117, 85, 48, 32, 255, 255, 170, 223, 255, 186, 186, 154, 101, 223, 207, 85, 154, 117, 117, 69, 32, 16, 255, 255, 138, 186, 207, 154, 101, 69, 32, 255, 239, 207, 239, 255, 170, 170, 138, 69, 255, 255, 223, 255, 223, 186, 186, 138, 69, 255, 239, 223, 207, 186, 170, 154, 138, 117, 101, 85, 69, 48, 32, 0 }; float [] pallet_b = { 255, 173, 156, 173, 99, 115, 82, 49, 49, 206, 115, 16, 66, 0, 99, 66, 0, 33, 189, 99, 33, 33, 0, 82, 0, 0, 16, 222, 206, 173, 140, 140, 99, 66, 49, 33, 255, 255, 222, 206, 255, 156, 173, 115, 66, 255, 255, 189, 239, 206, 115, 156, 99, 66, 156, 115, 49, 66, 0, 33, 0, 0, 0, 206, 115, 33, 0, 0, 0, 0, 0, 0, 255, 239, 206, 255, 255, 140, 156, 99, 49, 255, 255, 173, 239, 255, 140, 173, 99, 33, 189, 115, 16, 49, 49, 82, 0, 33, 16, 189, 140, 82, 140, 0, 156, 0, 0, 0, 255, 255, 156, 255, 255, 173, 115, 115, 66, 255, 255, 189, 206, 255, 173, 140, 82, 49, 239, 222, 173, 189, 206, 173, 156, 115, 49, 173, 115, 66, 0, 33, 82, 0, 0, 33, 255, 239, 222, 206, 189, 173, 156, 140, 115, 99, 82, 66, 49, 33, 0 }; void setup(){ context = new SimpleOpenNI(this); // enabling depth camera if(context.enableDepth() == false) { println("Can't open the depthMap, maybe the camera is not connected!"); exit(); return; } // enabling detecting human context.enableScene(); // enabling RGB camera if(context.enableRGB() == false) { println("Can't open the rgbMap, maybe the camera is not connected or there is no rgbSensor!"); exit(); return; } context.alternativeViewPointDepthToImage(); size(context.depthWidth() , context.depthHeight()); mm = new MovieMaker(this, context.depthWidth() , context.depthHeight(), "16bit.mov", fps, MovieMaker.VIDEO, MovieMaker.LOSSLESS); frameRate(fps); } void draw(){ context.update(); PImage maskImg = makeImgForMask(context.sceneImage()); PImage maskedImg = context.rgbImage(); // image(maskedImg, 0, 0); // display background PImage DotImg = ConvImgToDot(maskedImg); DotImg.mask(maskImg); // background real image(maskedImg, 0, 0); // real camera image background // background(0,64,0); // green mask background image(DotImg, 0, 0); // display mm.addFrame(); } PImage makeImgForMask(PImage img){ color cBlack = color(0, 0, 0); color cWhite = color(255, 255, 255); for (int x = 0; x < img.width; x++){ for (int y = 0; y < img.height; y++){ color c = img.get(x, y); if (red(c) == green(c) & green(c) == blue(c)){ // none human img.set(x, y, cBlack); // mask in black }else{ // human img.set(x, y, cWhite); // unmask in white } } } return img; } PImage ConvImgToDot(PImage img){ PImage writeImg; writeImg = createGraphics(img.width, img.height, P2D); img.loadPixels(); float[] img_r = new float[img.width*img.height]; float[] img_g = new float[img.width*img.height]; float[] img_b = new float[img.width*img.height]; float[] img16_r = new float[size_x*size_y]; float[] img16_g = new float[size_x*size_y]; float[] img16_b = new float[size_x*size_y]; int[] img16_pallet = new int[size_x*size_y]; for(int i = 0; i < img.width*img.height; i++){ color tmp_color = img.pixels[i]; img_r[i] = red(tmp_color); img_g[i] = green(tmp_color); img_b[i] = blue(tmp_color); } int div_x = int(img.width / size_x); int div_y = int(img.height / size_y); float tmp_r; float tmp_g; float tmp_b; // make dot image for(int i = 0; i < size_x*size_y; i++){ tmp_r = 0; tmp_g = 0; tmp_b = 0; int tmp_y = int(i / size_x); int tmp_x = i - size_x*tmp_y; for(int j = 0; j < div_x; j++){ for(int k = 0; k < div_y; k++){ tmp_r += img_r[tmp_x*div_x + tmp_y*img.width*div_y+ j + k*img.width]; tmp_g += img_g[tmp_x*div_x + tmp_y*img.width*div_y+ j + k*img.width]; tmp_b += img_b[tmp_x*div_x + tmp_y*img.width*div_y+ j + k*img.width]; } } tmp_r = tmp_r/(div_x*div_y); tmp_g = tmp_g/(div_x*div_y); tmp_b = tmp_b/(div_x*div_y); img16_r[i] = tmp_r; img16_g[i] = tmp_g; img16_b[i] = tmp_b; } writeImg.loadPixels(); // matching pallet for (int i = 0; i < size_x*size_y; i++) { float []tmp_color_distance = new float[n_pallet]; for (int j= 0; j < n_pallet; j++) { tmp_color_distance[j] = (img16_r[i] - pallet_r[j])*(img16_r[i] - pallet_r[j]) + (img16_g[i] - pallet_g[j])*(img16_g[i] - pallet_g[j]) + (img16_b[i] - pallet_b[j])*(img16_b[i] - pallet_b[j]); } float tmp_color_min = tmp_color_distance[0]; img16_pallet[i] = 0; for (int j= 1; j < n_pallet; j++) { if (tmp_color_min > tmp_color_distance[j]) { tmp_color_min = tmp_color_distance[j]; img16_pallet[i] = j; } } } // reduce pallet while (CountColor (img16_pallet, n_pallet) > max_color) { int []pallet_cnt = new int[n_pallet]; for (int i=0; i < n_pallet; i++) { pallet_cnt[i] = 0; for (int j= 0; j < size_x*size_y; j++) { if (img16_pallet[j] == i) { pallet_cnt[i]++; } } } int min_colornumb = 0; int first_cnt=0; int min_tmp = 0; while (pallet_cnt[first_cnt] == 0) { first_cnt++; } int min_colorcnt = pallet_cnt[first_cnt]; for (int i=first_cnt; i < n_pallet; i++) { if (min_colorcnt > pallet_cnt[i] && pallet_cnt[i] > 0) { min_tmp = 1; min_colorcnt = pallet_cnt[i]; min_colornumb = i; } } float min_colordist = 0; int neardist_colornumb = 0; if (min_tmp == 0) { min_colornumb = first_cnt; int tmp_cnt = first_cnt+1; while (pallet_cnt[tmp_cnt] == 0) { tmp_cnt++; } min_colordist = (pallet_r[min_colornumb]-pallet_r[tmp_cnt])*(pallet_r[min_colornumb]-pallet_r[tmp_cnt]) + (pallet_g[min_colornumb]-pallet_g[tmp_cnt])*(pallet_g[min_colornumb]-pallet_g[tmp_cnt]) + (pallet_b[min_colornumb]-pallet_b[tmp_cnt])*(pallet_b[min_colornumb]-pallet_b[tmp_cnt]); neardist_colornumb = tmp_cnt; } else { min_colordist = (pallet_r[min_colornumb]-pallet_r[first_cnt])*(pallet_r[min_colornumb]-pallet_r[first_cnt]) + (pallet_g[min_colornumb]-pallet_g[first_cnt])*(pallet_g[min_colornumb]-pallet_g[first_cnt]) + (pallet_b[min_colornumb]-pallet_b[first_cnt])*(pallet_b[min_colornumb]-pallet_b[first_cnt]); neardist_colornumb = first_cnt; } for (int i=first_cnt; i < n_pallet; i++) { if (pallet_cnt[i] > 0 && i != min_colornumb) { float tmp_dist = (pallet_r[min_colornumb]-pallet_r[i])*(pallet_r[min_colornumb]-pallet_r[i]) + (pallet_g[min_colornumb]-pallet_g[i])*(pallet_g[min_colornumb]-pallet_g[i]) + (pallet_b[min_colornumb]-pallet_b[i])*(pallet_b[min_colornumb]-pallet_b[i]); if (min_colordist > tmp_dist) { min_colordist = tmp_dist; neardist_colornumb = i; } } } for (int i=0; i < size_x*size_y; i++) { if (img16_pallet[i] == min_colornumb) { img16_pallet[i] = neardist_colornumb; } } } // pallet update for (int i = 0; i < size_x*size_y; i++) { img16_r[i] = pallet_r[img16_pallet[i]]; img16_g[i] = pallet_g[img16_pallet[i]]; img16_b[i] = pallet_b[img16_pallet[i]]; } // making dot image for(int i = 0; i < size_x*size_y; i++){ int tmp_y = int(i / size_x); int tmp_x = i - size_x*tmp_y; for(int j = 0; j < scale; j++){ for(int k = 0; k < scale; k++){ writeImg.pixels[tmp_y*size_x*scale*scale+tmp_x*scale+j*size_x*scale+k] = color(img16_r[i], img16_g[i], img16_b[i]); } } } writeImg.updatePixels(); return writeImg; } void keyPressed() { if (key == ' ') { mm.finish(); println("save movie."); exit(); } }