processing动作捕捉、xml传值、chrome静默打印(silent print),总之内容很多很丰富


这学期好多同学想做processing视频效果本地存储图片,结合传感器触发把图片自动用打印机打印出来。

 
在实际测试中,先用了java驱动打印机(网上也有相关文章),但没有成功。之后想到了用chrome浏览器的静默打印(参考这篇文章:http://www.blogjava.net/pojo/archive/2014/04/24/412891.html),使用xml在processing和chrome之间进行传值,监测到特定值后,延时自动打印图片,果然这个方法可行。
传感器这块儿,发现红外也好,超声波也好,干扰相对都太大。所以既然用了processing的capture video,干脆直接写个人体动作捕捉做触发,就不用任何物理传感器了。关于processing视频做触发这块儿,见这个人文章中的背景移除和动作捕捉这块儿,还是不错的(http://learn.travelchinawith.me/?p=783),我也是在他的算法基础上,写的触发器算法。
总结一下总体流程,首先processing捕获像素做效果,当发现frontground出现物体,和初始设定的background不一样的时候,保存帧画面并传给xml值1,否则,如果视频和初始background一样的话,传给xml值0,并不做任何动作。chrome通过js读取xml的值,如果发现是1的话,延时10s静默打印processing保存出的帧画面。
上processing代码:

import processing.video.*;
XML xml;
PImage backgroundImage;
float threshold = 36;//前景和后景色差阈值
//定义背景颜色(做效果用)
int bgColorR;
int bgColorG;
int bgColorB;
Capture video;
void setup() {
  size(640,480);
  video = new Capture(this, width, height, 30);
  video.start();
  backgroundImage = createImage(video.width,video.height,RGB);//初始化背景图
  bgColorR=int(random(0,7650));
  bgColorG=int(random(0,7650));
  bgColorB=int(random(0,7650));
}
void draw() {
  if (video.available()) {
    video.read();
  }
  loadPixels();
  video.loadPixels();
  int fgCount = 0;//每一帧开始的时候,初始化前景像素数量计数
  for (int x = 0; x < video.width; x +=20 ) {
    for (int y = 0; y < video.height; y +=20 ) {
      int loc = x+y*video.width;
      color fgColor = video.pixels[loc];//视频流像素取色
      color bgColor = backgroundImage.pixels[loc];//初始保存的背景图像素取色
      float d=brightness(video.pixels[loc]);//像素明度取色
      float r1 = red(fgColor);
      float g1 = green(fgColor);
      float b1 = blue(fgColor);
      float r2 = red(bgColor);
      float g2 = green(bgColor);
      float b2 = blue(bgColor);
      float diff = dist(r1,g1,b1,r2,g2,b2);//视频流像素颜色和初始保存的背景图像素颜色做对比
      int point = int(random(0, 33));
      int ra=int(random(0,35));
      //如果色差大于阈值,代表这个像素是新进入到视频流的前景像素,反之,则是初始保存的背景。分别给他们做效果。
      if (diff > threshold)
      {
        fgCount++;//如果这个像素是新进入到的视频流的前景像素,那么前景像素自+1
        color c = color(r1, g1, b1, 100);
        pushMatrix();
        translate(width-x-10, y+10);
        fill(c);
        stroke(c);
        strokeWeight(1.5);
        noFill();
        if (d>=0&&d<30) {
          stroke(c);
          fill(c);
          rect(0, 0, point, point);
        } else if (d>=30&&d<=50) {
          stroke(c);
          fill(c, 180);
          ellipse(0, 0, ra, ra);
        } else if (d>=51&&d<=80) {
          stroke(c);
          rect(0, 0, point, point);
        } else if (d>=81&&d<=100) {
          stroke(c);
          rect(0, 0, point, point);
        } else if (d>=101&&d<=150) {
          stroke(c);
          rect(0, 0, point, point);
        } else if (d>=151&&d<=220) {
          stroke(c);
          ellipse(0, 0, ra-5, ra-5);
        } else if (d>=220&&d<=255) {
          stroke(c);
          fill(c, 180);
          rect(0, 0, point, point);
        }
        popMatrix();
      }
      else {
        bgColorR+=int(random(0,4));
        bgColorG+=int(random(0,4));
        bgColorB+=int(random(0,4));
        if(bgColorR>7650){
          bgColorR=int(random(0,7650));
        }
        if(bgColorG>7650){
          bgColorG=int(random(0,7650));
        }
        if(bgColorB>7650){
          bgColorB=int(random(0,7650));
        }
        color c = color(bgColorR/30, bgColorG/30, bgColorB/30, 100);
        pushMatrix();
        translate(width-x-10, y+10);
        rectMode(CENTER);
        fill(c);
        stroke(c);
        strokeWeight(1.5);
        noFill();
        popMatrix();
      }
    }
  }
  println(fgCount);
  //当这一帧像素循环跑完后,看看本帧当中的前景像素数如果大于100,基本说明有物体进入到视频画面中,可以改变xml值,并保存出这一帧图像
  if(fgCount>100){
    xml = loadXML("printbool.xml");
    XML firstChild = xml.getChild("a");
    firstChild.setContent("1");
    saveXML(xml, "printbool.xml");
    saveFrame("Print"+".jpg");
  }else{
    xml = loadXML("printbool.xml");
    XML firstChild = xml.getChild("a");
    firstChild.setContent("0");
    saveXML(xml, "printbool.xml");
  }
}
//鼠标点击,记录背景帧画面
void mousePressed() {
  backgroundImage.copy(video,0,0,video.width,video.height,0,0,video.width,video.height);
  backgroundImage.updatePixels();
}
 --------------------------
xml文件,很短,就2个标签:
<?xml version="1.0" encoding="UTF-8"?>
<printbool>
  <a id="0">1</a>
</printbool>
---------------------------
html文件代码,具体内容不多介绍了,主要是js部分的实现,基本上思路就是调用xml的值做判断,如果是1就延时10s打印:
<html>
<head>
</head>
<script language="javascript" src="jquery-1.4.4.min.js"></script>
<script language="javascript" src="jquery.jqprint-0.3.js"></script>
<!--
<script src="http://code.jquery.com/jquery-migrate-1.1.0.js"></script>
-->
<script language="javascript">
function  a(){
        $("#ddd").jqprint();
    }
</script>
<script>
    var p;
	var time=0;
	function changesrc(){
    var pic=document.getElementById('change');
    var img='Print.jpg?'+new Date;
    pic.src=img;
	$(document).ready(function() {
    $.ajax({
        url: 'printbool.xml',
        type: 'GET',
        dataType: 'xml',
        timeout: 1000,  //设定超时
        cache: false,   //禁用缓存
        error: function(xml) {
            //alert("加载XML文档出错!");
        },
        success: GetStudentComplete   //设置成功后回调函数
    });
	});
	//获取XML成功后回调函数
	function GetStudentComplete(xml) {
		$(xml).find("printbool").each(function(i) {     //查找所有printbool节点并遍历
			var id = $(this).children("a");          //获得子节点
			var id_vaule = id.text();                 //获取节点文本
			  //获取节点的属性
			p=parseInt(id_vaule);
			if(p==1){
				//$("#ddd").jqprint();
				//p=0;
				time++;
				//alert(time);
				if(time>100){
					printImage();
					time=0;
				}
			}
		});
	}
    window.setTimeout(changesrc,100);
	}
	function printImage(){
		$("#ddd").jqprint();
		//alert(p);
	}
	window.onload=function(){
    	changesrc();
	}
</script>
<body style="margin:auto;">
<div id="ddd">
	<div style="height:495px;width:350px;border:15px solid #888888;">
	<img id="change" src="Print.jpg" style="width:350px;"/>
	<img id="logo" src="logo.jpg" style="width:350px;"/>
	<img>
	</div>
</div>
<input type="button" onclick=" a()" value="打印"/>
</body>
</html>
-------------------------------
最后,上张图:



发表评论

您的电子邮箱地址不会被公开。