- 浏览: 223590 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
haozyc:
谢谢 帮助很大
Google App Engine不再仅仅是诱人 -
每个人都可爱:
Hibernate dtd 这个问题太坑爹了
通过AppFuse创建ssh工程问题总结 -
up2pu:
mesopotamiaa 写道你好,pom.xml文件是哪个目 ...
JBoss Hibernate Tools 3.4.0与AppFuse -
mesopotamiaa:
你好,pom.xml文件是哪个目录中的?
JBoss Hibernate Tools 3.4.0与AppFuse -
aze:
安卓市场快烂透了吧 一进后台满屏的铜臭味这个广告位那个广告位的 ...
安卓市场上传应用对广告平台进行限制
【翻译】基于HTML5,javascript,webrtc,websockets,Jetty和OpenCV的人脸识别
- 博客分类:
- Translation
原文地址:
http://www.smartjava.org/content/face-detection-using-html5-javascript-webrtc-websockets-jetty-and-javacvopencv
对于HTML5和相关标准,每个新版本的现代浏览器提供了越来越多的标准特性。很多人已经听说过websockets,它可以让你很容易地建立到服务端的双向通讯通道,其背后是没有广泛宣传的webrtc规范。
使用webrtc规范可以通过HTML/Javascript很容易地实现实时视频、音频相关的应用。在应用中你可以使用用户的麦克风和摄像头,并将这些内容分享给互联网上其他用户。例如,你可以建立一个不需要插件的视频会议软件,或者一个使用手机查看的儿童监控软件,或者仅仅使网络直播更容易。完全可以使用跨浏览器特性替代插件。
更新:在最新版的webrtc规范中,我们可以访问麦克风资源!参考如下链接:
http://www.smartjava.org/content/record-audio-using-webrtc-chrome-and-speech-recognition-websockets
HTML5相关的众多规范中,webrtc还没有完成,在浏览器中的支持也很少。然而,你可以使用开发版Opera和最新版Chrome支持的特性实现一些很酷的功能。本文中,我将带领大家使用webrtc和一些HTML5其他标准实现如下功能:
为此我们需要做如下操作:
1.通过getUserMedia特性访问用户摄像头
2.使用websockets向服务端发送数据
3.在服务端,分析收到的数据,使用JavaCV/OpenCV检测和标记识别出来的人脸
4.使用websockets将数据从服务端发送到客户端
5.客户端显示从服务端收到的信息
换句话说,我们要创建一个实时的人脸识别系统,前端完全通过“标准的”HTML5/Javascript实现。在文章中你会看到,我们将使用一些小技巧,因为有些HTML5的特性还没有实现。
【up2pu.iteye.com翻译】
我们使用哪些工具和技术
让我们看看我们用来实现人脸识别系统的工具和技术。我们从前端技术开始:
1.Webrtc:规范是这么说的:这些API应该使得应用可以在浏览器中运行,不需要额外的下载和插件,允许各方使用音频、视频进行实时通信,不需要使用中介服务器(除非用于防火墙穿透或者提供中间服务)。
参考:http://www.w3.org/2011/04/webrtc-charter.html
2.Websockets:使得Web应用可以通过服务端处理实现双向通信,规范中介绍了WebSocket接口。
参考:http://dev.w3.org/html5/websockets/
3.Canvas:元素提供带有解决方案无关位图画布的脚本,用来实现图像渲染,游戏图像或者其他视觉图像。
参考:http://www.w3.org/wiki/HTML/Elements/canvas
我们在后台使用什么:
1.Jetty:提供websockets实现。
参考:http://www.eclipse.org/jetty/
2.OpenCV:一个提供各种图像处理算法的库。我们使用他们提供的算法实现人脸识别。
参考:http://opencv.willowgarage.com/wiki/
参考:http://opencv.willowgarage.com/wiki/FaceDetection
3.JavaCV:我们在Jetty中使用OpenCV对收到的数据进行图像检测。使用JavaCV我们可以通过Java使用OpenCV的特性。
参考:http://code.google.com/p/javacv/
【up2pu.iteye.com翻译】
前端第一步:开启Chrome的mediastream功能并访问摄像头
我们先访问摄像头。在我的例子中,我使用的是Chrome的最新版本(canay),该版本已经支持我们需要的webrtc规范。在使用前,你需要先开启它。打开“chrome://flags/”URL,然后开启mediastream功能。
一旦你开启它,就可以在不使用插件的情况下,通过浏览器使用webrtc的一些功能来访问摄像头。访问摄像头需要做的就是使用下面的html和javascript:
和下面的javascript:
使用这么小一段HTML和javascript代码,我们就可以访问用户的摄像头并在HTML5视频标签中显示出来。首先,我们使用getUserMedia(使用了chrome特有的webkit前缀)函数获得对摄像头的访问权限。在回调函数中,我们访问流对象。这个流对象就是用户摄像头产生的流。为了显示这个流,我们需要把它添加到视频标签上。视频标签的src属性允许我们设置一个URL用于播放。通过HTML5的另一个特性,我们把流转换成URL。该功能通过URL.CreateObjectURL(也是带有前缀的)函数实现。该函数返回值是个URL,我们把它添加到视频标签上。这就是访问用户摄像头视频流的全部过程。
下面我们要做的是通过websockets向jetty服务端发送视频流。
【up2pu.iteye.com翻译】
前端第二步:通过websockets向Jetty服务端发送视频流
这一步,我们想要从视频流获得数据,然后以二进制的方式通过websockets发送到Jetty服务端。理论上听起来很简单。我们已经得到了二进制的视频流,所以我们可以直接访问字节数据,然后通过websockets发送到远程服务端。然而,事实上行不通。通过getUserMedia得到的流对象,我们无法以流的方式访问它的数据。乐观点说,现在还不行。如果看一下规范,你可以发现,你应该能调用record()来访问recorder。这个recorder可以用来访问元数据。但是不幸的是,目前没有浏览器支持该功能。所以我们需要找个替代方案。现在看只有一个选择:
1.对当前视频截图
2.然后绘制到canvas标签上
3.从canvas获得数据,生成图片
4.通过websockets发送图片数据
这些小技巧导致一些客户端额外的处理和大量的数据发送到服务端,但是它可以用。实现这个也不那么难:
也不比前段的代码复杂多少。我们加了一个定时器和一个canvas。定时器250ms运行一次,把当前视频图像画到canvas上(可以通过下面的截屏看到)。
你可以看到canvas有点延迟。你可以把间隔时间调小,但是这样会消耗更多的资源。
下一步从canvas获取图像,然后转换成二进制,然后通过websocket发送出去。在我们看websocket部分前,先看看数据部分。为了获得数据,我们扩展了定时器函数的代码:
toDataURL函数从当前canvas复制数据,然后储存在dataurl中。dataurl是一个包含base64编码的二进制数据。在我们的例子中它看起来像下面这样:
我们可以以文本的方式发送它,然后在服务端解析,但是websockets允许我们直接发送二进制数据,我们把它转换成二进制数据。我们需要两步,canvas不允许(或者是我不知道)我们直接访问二进制数据。幸运的是,有人在stackoverflow创建了一个很好用的帮助方法(dataURItoBlob),这就是我们需要的(参考:http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata/5100158)。这时我们已经可以按照指定时间间隔获得包含当前视频截屏的数据数组。下一步,也是最后一步,在客户端通过websockets发送数据即可。
在Javascript中使用websockets非常简单。你只需要指定websockets的url并实现一些回调函数。首先需要打开连接:
如果一切顺利,我们现在有了一个双向连接。通过这个连接发送数据只需要调用ws.send:
这就是客户端的代码。如果我们打开这个页面,我们首先获取用户摄像头的访问权限,然后在视屏标签中显示从摄像头获得的数据流,按照指定间隔时间捕获视频数据,通过websockets发送到后台服务进行后续处理。
【up2pu.iteye.com翻译】
建立后台服务环境
本例的后台服务使用Jetty的websocket支持(后续文章中,我会看看能否在Play 2.0 websockets支持的情况下运行)。使用Jetty可以很方便的启动一个带有websocket监听的服务端。我经常运行嵌入式Jetty,使用如下简单的Jetty启动器使websockets运行起来。
很长的一段代码,但是理解起来并不困难。引入的部分用来创建一个处理器支持websocket协议。这里我们创建一个WebSocketHandler,它总是返回同一个WebSocket。在真实的场景中,你需要根据属性和URL决定WebSocket的类型,本例中我们只需要一直返回同一个。
websocket本身没有那么复杂,但是为了正确运行我们需要配置一些东西。在onOpen方法中我们做了如下事情:
该操作开启二进制消息支持。现在我们的WebSocket可以接收不大于512KB的二进制消息,因为我们没有直接把数据以流的方式发送,而是发送了一个canvas渲染的图片,因此消息非常大。512KB对于640*480已经够了。我们的人脸识别程序在320*240下工作很好,这就够了。对收到的二进制图片数据的处理在onMessage方法中实现:
代码没有优化,但是目的很明确。我们得到客户端发送的数据,然后把它写到固定大小的byte数组,传递给faceDetection类。faceDetection类做一些神奇的事情然后返回处理的图片。这个处理后的图片和原始的一样,只是增加了黄色矩形表示被识别的人脸。
处理后的图像通过同一个websocket连接发送到客户端进行后续处理。在看数据怎么用javascript显示前,我们先看看FaceDetection类。FaceDetection类使用JavaCV(OpenCV的Java封装)中的CvHaarClassifierCascade来检测人脸。我不会深入介绍人脸识别是如何实现的,因为它本身就是一个比较大的话题。
代码至少解释了步骤。想进一步了解它如何生效可以查看OpenCV和JavaCV网站。通过改变关联文件,修改minsize,group,scale等属性,你可以使用它识别眼睛,鼻子,耳朵,瞳孔等。例如人眼识别看起来像下面这样:
【up2pu.iteye.com翻译】
前端,显示识别出来的人脸
最后一步是接收Jetty的web应用发送的消息,然后在img标签中渲染。我们通过设置websocket的onmessage函数实现。下面的代码中,我们接收到二进制消息。然后将消息转换成objectURL(可以把它看做一个本地的、临时的URL),然后将它设置为图像的源。一旦图像被加载,我们回收objectURL,因为它已经没用了。
现在,我们需要更新一下html为如下形式:
现在我们已经实现了人脸识别:
正如你所看到,使用新的HTML5 API可以实现很多功能。遗憾的是不是所有功能都实现了,并且某些情况下浏览器支持的也不好。但是,它确实给我们提供了一些精彩又强大的特性。我已经在最新版本的Chrome和Safari中测试(在Safari中使用需要去掉webkit前缀)。它应该也能运行在开启了“userMedia”功能的safari手机浏览器中。确定你是在使用高带宽的WIFI,因为代码没有针对带宽做任何优化。几周后我还会再看看这篇文章,如果有时间,我会实现一个基于Play2/Scala的后台服务版本。
参考资料:
http://www.html5china.com/course/20120528_3742.html
http://neave.com/webcam/html5/face/(一个demo)
http://www.smartjava.org/content/face-detection-using-html5-javascript-webrtc-websockets-jetty-and-javacvopencv
人脸识别
——基于HTML5,javascript,webrtc,websockets,Jetty和OpenCV
By jos.dirksen on Thu, 04/19/2012 - 15:57
——基于HTML5,javascript,webrtc,websockets,Jetty和OpenCV
By jos.dirksen on Thu, 04/19/2012 - 15:57
对于HTML5和相关标准,每个新版本的现代浏览器提供了越来越多的标准特性。很多人已经听说过websockets,它可以让你很容易地建立到服务端的双向通讯通道,其背后是没有广泛宣传的webrtc规范。
使用webrtc规范可以通过HTML/Javascript很容易地实现实时视频、音频相关的应用。在应用中你可以使用用户的麦克风和摄像头,并将这些内容分享给互联网上其他用户。例如,你可以建立一个不需要插件的视频会议软件,或者一个使用手机查看的儿童监控软件,或者仅仅使网络直播更容易。完全可以使用跨浏览器特性替代插件。
更新:在最新版的webrtc规范中,我们可以访问麦克风资源!参考如下链接:
http://www.smartjava.org/content/record-audio-using-webrtc-chrome-and-speech-recognition-websockets
HTML5相关的众多规范中,webrtc还没有完成,在浏览器中的支持也很少。然而,你可以使用开发版Opera和最新版Chrome支持的特性实现一些很酷的功能。本文中,我将带领大家使用webrtc和一些HTML5其他标准实现如下功能:
为此我们需要做如下操作:
1.通过getUserMedia特性访问用户摄像头
2.使用websockets向服务端发送数据
3.在服务端,分析收到的数据,使用JavaCV/OpenCV检测和标记识别出来的人脸
4.使用websockets将数据从服务端发送到客户端
5.客户端显示从服务端收到的信息
换句话说,我们要创建一个实时的人脸识别系统,前端完全通过“标准的”HTML5/Javascript实现。在文章中你会看到,我们将使用一些小技巧,因为有些HTML5的特性还没有实现。
【up2pu.iteye.com翻译】
我们使用哪些工具和技术
让我们看看我们用来实现人脸识别系统的工具和技术。我们从前端技术开始:
1.Webrtc:规范是这么说的:这些API应该使得应用可以在浏览器中运行,不需要额外的下载和插件,允许各方使用音频、视频进行实时通信,不需要使用中介服务器(除非用于防火墙穿透或者提供中间服务)。
参考:http://www.w3.org/2011/04/webrtc-charter.html
2.Websockets:使得Web应用可以通过服务端处理实现双向通信,规范中介绍了WebSocket接口。
参考:http://dev.w3.org/html5/websockets/
3.Canvas:元素提供带有解决方案无关位图画布的脚本,用来实现图像渲染,游戏图像或者其他视觉图像。
参考:http://www.w3.org/wiki/HTML/Elements/canvas
我们在后台使用什么:
1.Jetty:提供websockets实现。
参考:http://www.eclipse.org/jetty/
2.OpenCV:一个提供各种图像处理算法的库。我们使用他们提供的算法实现人脸识别。
参考:http://opencv.willowgarage.com/wiki/
参考:http://opencv.willowgarage.com/wiki/FaceDetection
3.JavaCV:我们在Jetty中使用OpenCV对收到的数据进行图像检测。使用JavaCV我们可以通过Java使用OpenCV的特性。
参考:http://code.google.com/p/javacv/
【up2pu.iteye.com翻译】
前端第一步:开启Chrome的mediastream功能并访问摄像头
我们先访问摄像头。在我的例子中,我使用的是Chrome的最新版本(canay),该版本已经支持我们需要的webrtc规范。在使用前,你需要先开启它。打开“chrome://flags/”URL,然后开启mediastream功能。
一旦你开启它,就可以在不使用插件的情况下,通过浏览器使用webrtc的一些功能来访问摄像头。访问摄像头需要做的就是使用下面的html和javascript:
<div> <video id="live" width="320" height="240" autoplay></video> </div>
和下面的javascript:
video = document.getElementById("live") var ctx; // use the chrome specific GetUserMedia function navigator.webkitGetUserMedia("video", function(stream) { video.src = webkitURL.createObjectURL(stream); }, function(err) { console.log("Unable to get video stream!") } )
使用这么小一段HTML和javascript代码,我们就可以访问用户的摄像头并在HTML5视频标签中显示出来。首先,我们使用getUserMedia(使用了chrome特有的webkit前缀)函数获得对摄像头的访问权限。在回调函数中,我们访问流对象。这个流对象就是用户摄像头产生的流。为了显示这个流,我们需要把它添加到视频标签上。视频标签的src属性允许我们设置一个URL用于播放。通过HTML5的另一个特性,我们把流转换成URL。该功能通过URL.CreateObjectURL(也是带有前缀的)函数实现。该函数返回值是个URL,我们把它添加到视频标签上。这就是访问用户摄像头视频流的全部过程。
下面我们要做的是通过websockets向jetty服务端发送视频流。
【up2pu.iteye.com翻译】
前端第二步:通过websockets向Jetty服务端发送视频流
这一步,我们想要从视频流获得数据,然后以二进制的方式通过websockets发送到Jetty服务端。理论上听起来很简单。我们已经得到了二进制的视频流,所以我们可以直接访问字节数据,然后通过websockets发送到远程服务端。然而,事实上行不通。通过getUserMedia得到的流对象,我们无法以流的方式访问它的数据。乐观点说,现在还不行。如果看一下规范,你可以发现,你应该能调用record()来访问recorder。这个recorder可以用来访问元数据。但是不幸的是,目前没有浏览器支持该功能。所以我们需要找个替代方案。现在看只有一个选择:
1.对当前视频截图
2.然后绘制到canvas标签上
3.从canvas获得数据,生成图片
4.通过websockets发送图片数据
这些小技巧导致一些客户端额外的处理和大量的数据发送到服务端,但是它可以用。实现这个也不那么难:
var video = $("#live").get()[0]; var canvas = $("#canvas"); var ctx = canvas.get()[0].getContext('2d'); navigator.webkitGetUserMedia("video", function(stream) { video.src = webkitURL.createObjectURL(stream); }, function(err) { console.log("Unable to get video stream!") } ) timer = setInterval( function () { ctx.drawImage(video, 0, 0, 320, 240); }, 250);
也不比前段的代码复杂多少。我们加了一个定时器和一个canvas。定时器250ms运行一次,把当前视频图像画到canvas上(可以通过下面的截屏看到)。
你可以看到canvas有点延迟。你可以把间隔时间调小,但是这样会消耗更多的资源。
下一步从canvas获取图像,然后转换成二进制,然后通过websocket发送出去。在我们看websocket部分前,先看看数据部分。为了获得数据,我们扩展了定时器函数的代码:
timer = setInterval( function () { ctx.drawImage(video, 0, 0, 320, 240); var data = canvas.get()[0].toDataURL('image/jpeg', 1.0); newblob = dataURItoBlob(data); }, 250); }
toDataURL函数从当前canvas复制数据,然后储存在dataurl中。dataurl是一个包含base64编码的二进制数据。在我们的例子中它看起来像下面这样:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCADwAUADASIAAhEBAxEB/8QAHwAAAQU .. snip .. QxL7FDBd+0sxJYZ3Ma5WOSYxwMEBViFlRvmIUFmwUO7O75Q4OSByS5L57xcoJuVaSTTpyfJ RSjKfxayklZKpzXc1zVXVpxlGRKo1K8pPlje6bs22oxSau4R9289JNJuLirpqL4p44FcQMkYMjrs+z vhpNuzDBjlmJVADuwMLzsIy4OTMBvAxuDM+AQW2vsVzIoyQQwG1j8hxt6VELxd7L5caoT5q4kj uc4rku4QjOPI4tNXxkua01y8uijJtSTS80le0Z6WjJuz5pXaa//2Q==
我们可以以文本的方式发送它,然后在服务端解析,但是websockets允许我们直接发送二进制数据,我们把它转换成二进制数据。我们需要两步,canvas不允许(或者是我不知道)我们直接访问二进制数据。幸运的是,有人在stackoverflow创建了一个很好用的帮助方法(dataURItoBlob),这就是我们需要的(参考:http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata/5100158)。这时我们已经可以按照指定时间间隔获得包含当前视频截屏的数据数组。下一步,也是最后一步,在客户端通过websockets发送数据即可。
在Javascript中使用websockets非常简单。你只需要指定websockets的url并实现一些回调函数。首先需要打开连接:
var ws = new WebSocket("ws://127.0.0.1:9999"); ws.onopen = function () { console.log("Openened connection to websocket"); }
如果一切顺利,我们现在有了一个双向连接。通过这个连接发送数据只需要调用ws.send:
timer = setInterval( function () { ctx.drawImage(video, 0, 0, 320, 240); var data = canvas.get()[0].toDataURL('image/jpeg', 1.0); newblob = dataURItoBlob(data); ws.send(newblob); }, 250); }
这就是客户端的代码。如果我们打开这个页面,我们首先获取用户摄像头的访问权限,然后在视屏标签中显示从摄像头获得的数据流,按照指定间隔时间捕获视频数据,通过websockets发送到后台服务进行后续处理。
【up2pu.iteye.com翻译】
建立后台服务环境
本例的后台服务使用Jetty的websocket支持(后续文章中,我会看看能否在Play 2.0 websockets支持的情况下运行)。使用Jetty可以很方便的启动一个带有websocket监听的服务端。我经常运行嵌入式Jetty,使用如下简单的Jetty启动器使websockets运行起来。
public class WebsocketServer extends Server { private final static Logger LOG = Logger.getLogger(WebsocketServer.class); public WebsocketServer(int port) { SelectChannelConnector connector = new SelectChannelConnector(); connector.setPort(port); addConnector(connector); WebSocketHandler wsHandler = new WebSocketHandler() { public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { return new FaceDetectWebSocket(); } }; setHandler(wsHandler); } /** * Simple innerclass that is used to handle websocket connections. * * @author jos */ private static class FaceDetectWebSocket implements WebSocket, WebSocket.OnBinaryMessage, WebSocket.OnTextMessage { private Connection connection; private FaceDetection faceDetection = new FaceDetection(); public FaceDetectWebSocket() { super(); } /** * On open we set the connection locally, and enable * binary support */ public void onOpen(Connection connection) { this.connection = connection; this.connection.setMaxBinaryMessageSize(1024 * 512); } /** * Cleanup if needed. Not used for this example */ public void onClose(int code, String message) {} /** * When we receive a binary message we assume it is an image. We then run this * image through our face detection algorithm and send back the response. */ public void onMessage(byte[] data, int offset, int length) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); bOut.write(data, offset, length); try { byte[] result = faceDetection.convert(bOut.toByteArray()); this.connection.sendMessage(result, 0, result.length); } catch (IOException e) { LOG.error("Error in facedetection, ignoring message:" + e.getMessage()); } } } /** * Start the server on port 999 */ public static void main(String[] args) throws Exception { WebsocketServer server = new WebsocketServer(9999); server.start(); server.join(); } }
很长的一段代码,但是理解起来并不困难。引入的部分用来创建一个处理器支持websocket协议。这里我们创建一个WebSocketHandler,它总是返回同一个WebSocket。在真实的场景中,你需要根据属性和URL决定WebSocket的类型,本例中我们只需要一直返回同一个。
websocket本身没有那么复杂,但是为了正确运行我们需要配置一些东西。在onOpen方法中我们做了如下事情:
public void onOpen(Connection connection) { this.connection = connection; this.connection.setMaxBinaryMessageSize(1024 * 512); }
该操作开启二进制消息支持。现在我们的WebSocket可以接收不大于512KB的二进制消息,因为我们没有直接把数据以流的方式发送,而是发送了一个canvas渲染的图片,因此消息非常大。512KB对于640*480已经够了。我们的人脸识别程序在320*240下工作很好,这就够了。对收到的二进制图片数据的处理在onMessage方法中实现:
public void onMessage(byte[] data, int offset, int length) { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); bOut.write(data, offset, length); try { byte[] result = faceDetection.convert(bOut.toByteArray()); this.connection.sendMessage(result, 0, result.length); } catch (IOException e) { LOG.error("Error in facedetection, ignoring message:" + e.getMessage()); } }
代码没有优化,但是目的很明确。我们得到客户端发送的数据,然后把它写到固定大小的byte数组,传递给faceDetection类。faceDetection类做一些神奇的事情然后返回处理的图片。这个处理后的图片和原始的一样,只是增加了黄色矩形表示被识别的人脸。
处理后的图像通过同一个websocket连接发送到客户端进行后续处理。在看数据怎么用javascript显示前,我们先看看FaceDetection类。FaceDetection类使用JavaCV(OpenCV的Java封装)中的CvHaarClassifierCascade来检测人脸。我不会深入介绍人脸识别是如何实现的,因为它本身就是一个比较大的话题。
public class FaceDetection { private static final String CASCADE_FILE = "resources/haarcascade_frontalface_alt.xml"; private int minsize = 20; private int group = 0; private double scale = 1.1; /** * Based on FaceDetection example from JavaCV. */ public byte[] convert(byte[] imageData) throws IOException { // create image from supplied bytearray IplImage originalImage = cvDecodeImage(cvMat(1, imageData.length,CV_8UC1, new BytePointer(imageData))); // Convert to grayscale for recognition IplImage grayImage = IplImage.create(originalImage.width(), originalImage.height(), IPL_DEPTH_8U, 1); cvCvtColor(originalImage, grayImage, CV_BGR2GRAY); // storage is needed to store information during detection CvMemStorage storage = CvMemStorage.create(); // Configuration to use in analysis CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(cvLoad(CASCADE_FILE)); // We detect the faces. CvSeq faces = cvHaarDetectObjects(grayImage, cascade, storage, scale, group, minsize); // We iterate over the discovered faces and draw yellow rectangles around them. for (int i = 0; ipublic class FaceDetection { private static final String CASCADE_FILE = "resources/haarcascade_frontalface_alt.xml"; private int minsize = 20; private int group = 0; private double scale = 1.1; /** * Based on FaceDetection example from JavaCV. */ public byte[] convert(byte[] imageData) throws IOException { // create image from supplied bytearray IplImage originalImage = cvDecodeImage(cvMat(1, imageData.length,CV_8UC1, new BytePointer(imageData))); // Convert to grayscale for recognition IplImage grayImage = IplImage.create(originalImage.width(), originalImage.height(), IPL_DEPTH_8U, 1); cvCvtColor(originalImage, grayImage, CV_BGR2GRAY); // storage is needed to store information during detection CvMemStorage storage = CvMemStorage.create(); // Configuration to use in analysis CvHaarClassifierCascade cascade = new CvHaarClassifierCascade(cvLoad(CASCADE_FILE)); // We detect the faces. CvSeq faces = cvHaarDetectObjects(grayImage, cascade, storage, scale, group, minsize); // We iterate over the discovered faces and draw yellow rectangles around them. for (int i = 0; i < faces.total(); i++) { CvRect r = new CvRect(cvGetSeqElem(faces, i)); cvRectangle(originalImage, cvPoint(r.x(), r.y()), cvPoint(r.x() + r.width(), r.y() + r.height()), CvScalar.YELLOW, 1, CV_AA, 0); } // convert the resulting image back to an array ByteArrayOutputStream bout = new ByteArrayOutputStream(); BufferedImage imgb = originalImage.getBufferedImage(); ImageIO.write(imgb, "png", bout); return bout.toByteArray(); } }
代码至少解释了步骤。想进一步了解它如何生效可以查看OpenCV和JavaCV网站。通过改变关联文件,修改minsize,group,scale等属性,你可以使用它识别眼睛,鼻子,耳朵,瞳孔等。例如人眼识别看起来像下面这样:
【up2pu.iteye.com翻译】
前端,显示识别出来的人脸
最后一步是接收Jetty的web应用发送的消息,然后在img标签中渲染。我们通过设置websocket的onmessage函数实现。下面的代码中,我们接收到二进制消息。然后将消息转换成objectURL(可以把它看做一个本地的、临时的URL),然后将它设置为图像的源。一旦图像被加载,我们回收objectURL,因为它已经没用了。
ws.onmessage = function (msg) { var target = document.getElementById("target"); url=window.webkitURL.createObjectURL(msg.data); target.onload = function() { window.webkitURL.revokeObjectURL(url); }; target.src = url; }
现在,我们需要更新一下html为如下形式:
<div style="visibility: hidden; width:0; height:0;"> <canvas width="320" id="canvas" height="240"></canvas> </div> <div> <video id="live" width="320" height="240" autoplay style="display: inline;"></video> <img id="target" style="display: inline;"/> </div>
现在我们已经实现了人脸识别:
正如你所看到,使用新的HTML5 API可以实现很多功能。遗憾的是不是所有功能都实现了,并且某些情况下浏览器支持的也不好。但是,它确实给我们提供了一些精彩又强大的特性。我已经在最新版本的Chrome和Safari中测试(在Safari中使用需要去掉webkit前缀)。它应该也能运行在开启了“userMedia”功能的safari手机浏览器中。确定你是在使用高带宽的WIFI,因为代码没有针对带宽做任何优化。几周后我还会再看看这篇文章,如果有时间,我会实现一个基于Play2/Scala的后台服务版本。
参考资料:
http://www.html5china.com/course/20120528_3742.html
http://neave.com/webcam/html5/face/(一个demo)
发表评论
-
【翻译】简单的JavaScript继承
2012-11-28 17:50 1529原文地址:http://ejohn.org ... -
【翻译】使用HTML5写游戏:第一步
2012-11-18 16:29 1685原文地址:http://jacebook.co.uk/blog ... -
【翻译】为什么今天谷歌无法访问以及互联网工作原理
2012-11-08 10:05 2029原文地址:http://blog.cloudflare.com ... -
【翻译】Windows Phone 8将会告诉用户在哪可以找到免费的Wi-Fi
2012-11-07 22:58 1089原文地址:http://www.pcadvisor.co.uk ...
相关推荐
基于python+webRTC+opencv来实现通信和检测小宝是否起床系统.zip 远程检测小宝睡觉(防摔床) 提供一个后台服务,并且可以通过手机或者平板,监测小宝是否起床。当起床后爬动手机会响起报警。 主要使用webRTC和...
在本项目中,“通过opencv实现的人脸识别web端”是一个基于OpenCV库的JavaScript应用程序,用于在Web浏览器环境中实现人脸识别功能。OpenCV(Open Source Computer Vision Library)是一个跨平台的计算机视觉库,...
3. **人脸识别**: 通过OpenCV的人脸检测和识别模块,系统可以识别驾驶员和其他乘客的面部特征,这可能用于身份验证或者疲劳驾驶预警等功能。OpenCV的Haar级联分类器和LBPH(局部二值模式直方图)算法是常用的人脸...
WebRTC是基于浏览器的Web技术,而移动智 能终端的最大共同点是都具备浏览器,因此WebRTC 几乎可以同时覆盖所有的移动智能终端,用户无需安 装软件就可以进行视频通信。而WebRTC又是基于 HTML5标准的开源技术,因此在...
Android平台上基于HTML5_WebRTC的视频会议系统
开发者可以基于此进一步扩展,比如添加多人视频聊天功能,或者利用OpenCV实现更复杂的计算机视觉任务,如物体识别、手势识别等。同时,这也是一个很好的实例,展示了如何将传统的本地计算机视觉技术无缝地融入到Web...
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用!...基于JavaScript WebRTC实现跨平台音视频通话(源码+项目说明)(实现1对1视频,多人视频,视频直播,视频会议,房间管理,权限管理等).zip
基于webrtc+clmtrackr.js实现的视频录制、人脸检测、活体检测源码+体验地址.zip 基于webrtc+clmtrackr.js实现的视频录制、人脸检测、活体检测源码+体验地址.zip 基于webrtc+clmtrackr.js实现的视频录制、人脸检测、...
通过人脸识别实现拍照登录和入会身份检验。.zip一个基于Vue3&Springboot&Tensorflow的音视频会议系统(毕业设计),音视频框架采用WebRTC。通过人脸识别实现拍照登录和入会身份检验。.zip一个基于Vue3&...
在本文中,我们将深入探讨如何使用纯JavaScript实现一个具有手动抓拍、自动抓拍功能的人脸识别服务,并能获取人脸照片。此服务还允许用户切换摄像头,为用户提供更灵活的操作体验。由于这是一个基于Web的应用,因此...
【资源说明】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下才上传的,请放心下载使用。 2、适用人群:主要针对计算机相关专业(如计科、信息安全、数据...通过人脸识别实现拍照登录和入会身份检验).zip
它读取视频流并传递给OpenCV图像处理线程进行人脸识别和打码处理。 (3)OpenCV图像处理线程:该线程利用OpenCV库进行人脸检测和打码。它从摄像头采集线程接收到的视频帧中提取人脸区域,然后将区域绘制为马赛克...
为了实现活体检测,实例可能利用复杂算法分析人脸的微小运动、眨眼、微笑等动态特征,以区分真实人脸和静态图像。这一步通常需要配合机器学习模型来提高准确率。 将这个实例部署到TOMCAT服务器上,意味着它是一个...
在IT领域,人脸识别技术是一种利用计算机视觉和模式识别技术来识别人脸特征的高级应用。在本项目"人脸识别拍照.rar"中,我们看到一个利用getUserMedia API和tracking.js库实现的简单人脸识别拍照系统。这个系统的...
【资源说明】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下...基于JavaScript WebRTC实现跨平台音视频通话(源码+项目说明)(实现1对1视频,多人视频,视频直播,视频会议,房间管理,权限管理等).zip
基于Vue实现的webrtc通话系统源码+运行说明.zip基于Vue实现的webrtc通话系统源码+运行说明.zip基于Vue实现的webrtc通话系统源码+运行说明.zip基于Vue实现的webrtc通话系统源码+运行说明.zip基于Vue实现的webrtc通话...
基于Nodejs和html实现webrtc通信项目源码(代码精简好用).zip基于Nodejs和html实现webrtc通信项目源码(代码精简好用).zip基于Nodejs和html实现webrtc通信项目源码(代码精简好用).zip基于Nodejs和html实现webrtc通信...
1. 客户端代码:使用JavaScript编写,集成WebRTC和XMPP的相关API,实现用户界面交互,获取媒体流,建立和管理RTCPeerConnection。 2. 服务器端代码:可能包含一个XMPP服务器,处理客户端的信令请求,例如连接、断开...
JavaScript 人脸识别技术是一种基于计算机视觉和深度学习的现代技术,它允许在网页上实时地检测、识别和跟踪人脸。在给定的“tracking.js-master.zip”压缩包中,包含了一个名为“tracking.js-master”的项目,这...
这个"HTML5 基于WEBRTC实现浏览器之间的P2P视频通话,支持手机与电脑通话.zip"文件应该包含了一个基于WebRTC的示例项目,名为"WebRTC_RTCPeer_FaceToFace_Demo-master",用于演示如何实现在不同设备之间进行面对面的...