惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Security Latest
Security Latest
P
Palo Alto Networks Blog
AWS News Blog
AWS News Blog
NISL@THU
NISL@THU
T
Threatpost
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Latest news
Latest news
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
J
Java Code Geeks
P
Privacy International News Feed
阮一峰的网络日志
阮一峰的网络日志
S
Schneier on Security
博客园 - 聂微东
Project Zero
Project Zero
美团技术团队
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Scott Helme
Scott Helme
I
Intezer
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Hacker News: Front Page
S
Security @ Cisco Blogs
博客园 - 司徒正美
O
OpenAI News
Last Week in AI
Last Week in AI
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
SecWiki News
SecWiki News
月光博客
月光博客
S
Security Affairs
The GitHub Blog
The GitHub Blog
P
Privacy & Cybersecurity Law Blog
S
Secure Thoughts
V
V2EX
S
Securelist
F
Fortinet All Blogs
W
WeLiveSecurity
D
Docker
博客园 - 三生石上(FineUI控件)
Simon Willison's Weblog
Simon Willison's Weblog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
V
Visual Studio Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Webroot Blog
Webroot Blog
Engineering at Meta
Engineering at Meta

博客园 - Asharp

使用PowerShell批量修改项目文件的版本号 PowerShell因为在此系统中禁止执行脚本解决方法 .NET中zip的压缩和解压——SharpCompress .NET中zip的压缩和解压 【转】Web实现音频、视频通信 【转】关于IPv6的六大误区:IPv6并非更安全 【转】Silverlight与Flex的比较选择 [转]12 很有用的 Chrome 浏览器命令 How to Set Up SSL on IIS 7 JavaScript实现md5加密 在64位系统32的.net应用程序出现CLR20R3错误 【转】CLR20R3 程序终止的几种解决方案 【转】ASPxGridView 日期范围过滤扩展 DevExpress的web.config配置 DevExpress的JavaScript脚本智能提示 加载托管C++程序集出现0x800736B1异常的解决方法 Exchange server 2007安装篇 使用Orca在Visual Studio安装项目中创建自定义对话框 Visual Assist X中文注释提示错误问题
【转】Face detection with getUserMedia
Asharp · 2012-05-28 · via 博客园 - Asharp

There are quite a few interesting APIs evolving in the "modern web", but not all of them are going to be things you would use in most projects. I've been very public about my feelings concerning canvas for example. Great for games and charting - but not much else. That doesn't make it a bad feature. It just makes it one I won't use terribly often. Whenever I read about some new cool feature being developed, my mind starts trying to figure out what they could be used for in a practical sense. Obviously what's practical to you may not be practical to me, but figuring out how I would actually use a feature is part of how I learn it.

One such feature is getUserMedia (W3C Spec). This is a JavaScript API that gives you access to (with permission) the user's web cam and microphone. getUserMedia is currently supported in Opera and Chrome (I believe it is in version 18 now, but you may need to grab Canary. You also need to enable it. Instructions on that here.) Once you get past actually enabling it, the API is rather simple. Here's a quick request for access:

//a video tag

var video = document.getElementById('monitor');

//request it

navigator.webkitGetUserMedia({video:true}, gotStream, noStream);

function gotStream(stream) {

video.src = webkitURL.createObjectURL(stream);

video.onerror = function () {

stream.stop();

streamError();

};

}

function noStream() {

document.getElementById('errorMessage').textContent = 'No camera available.';

}

function streamError() {

document.getElementById('errorMessage').textContent = 'Camera error.';

}

view rawgistfile1.jsThis Gist brought to you by GitHub.

The first argument to getUserMedia is the type. According to the spec, this is supposed to be an object where you enable audio, video, or both, like so: {audio:true, video:true}. However in my testing, passing a string, "video", worked fine. The demo you will be seeing is based on another demo so that line possibly came from an earlier build that still works with Chrome. The second and third arguments are your success and failure callbacks respectively.

You can see in the gist where the success handler assigns the video stream to an HTML5 video tag. What's cool then is that once you have that running you can use the Canvas API to take pictures. For a demo of this, check out Greg Miernicki's demo:

http://miernicki.com/cam.html

If this demo doesn't work for you - then stop - and try following the instructions again to enable support. (Although I plan on sharing a few screen shots so if you just want to keep reading, that's fine too.)

Based on Greg's demo, it occurred to me that there is something cool we can do with pictures of our web cams. (Cue the dirty jokes.) I remembered that Face.com had avery cool API for parsing pictures for faces. (I blogged a ColdFusion example back in November.) I wondered then if we could combine Greg's demo with the Face.com API to do some basic facial recognition.

Turns out there are a few significant issues with this. First - while Face.com has a nice REST API, how would we use it from a JavaScript application? Secondly - Face.com requires you to either upload a picture or give it a URL. I know I could send a canvas picture to a server and have my backend upload it to Face.com, but is there a way to bypass the server and send the picture right to the API?

The first issue actually turned out to be a non-issue. Face.com implements CORS(Cross-Origin Resource Sharing). CORS basically allows a server to expose itself to Ajax calls from documents on other domains. It's a great feature and I hope more services enable it.

The more complex issue then was taking the canvas data and sending it to Face.com. How can I fake a file upload? Turns out there's another cool new trick - FormData. Fellow ColdFusion blogger Sagar Ganatra has an excellent blog entry on the topic. Here's how I used it:

function snapshot() {

$("#result").html("<p><i>Working hard for the money...</i></p>");

canvas.width = video.videoWidth;

canvas.height = video.videoHeight;

canvas.getContext('2d').drawImage(video, 0, 0);

var data = canvas.toDataURL('image/jpeg', 1.0);

newblob = dataURItoBlob(data);

var formdata = new FormData();

formdata.append("api_key", faceKey);

formdata.append("api_secret", faceSecret);

formdata.append("filename","temp.jpg");

formdata.append("file",newblob);

$.ajax({

url: 'http://api.face.com/faces/detect.json?attributes=age_est,gender,mood,smiling,glasses',

    data: formdata,

cache: false,

contentType: false,

processData: false,

dataType:"json",

type: 'POST',

success: function (data) {

handleResult(data.photos[0]);

}

});

}

view rawgistfile1.jsThis Gist brought to you by GitHub.

Let's look at this line by line. First off - I need to get the binary data from the canvas object. There's a few ways of doing this, but I wanted a Binary Blob specifically. Notice the dataURIToBlob method. This comes from a StackOverflow post I found a few weeks back.

I create a new FormData object and then simply begin setting my values. You can see I pass in a few API requirements but the crucial parts are the filename and file object itself.

Below that you can see the simple jQuery Ajax call. Face.com has a variety of options, but I basically just asked it to return an estimated age, gender, mood, and whether or not the person was smiling and wearing glasses. That's it. I get a nice JSON packet back and format it.

Now obviously no API is perfect. I've had different levels of results from using the API. Sometimes it's pretty damn accurate and sometimes it isn't. Overall though it's pretty cool. Here are some scary pictures of yours truly testing it out.

Ok, ready to test it yourself? Just click the demo button below. For the entire source, just view source! This is 100% client-side code.

For another look at getUserMedia, check out these examples:

Edit on May 23: Chrome recently modified the getUserMedia API to match the spec (I believe) which requires you to pass an object of media you want, so instead of "video", I used {video:true}.