资讯专栏INFORMATION COLUMN

用OpenCV在浏览器进行人脸检测

zengdongbao / 2820人阅读

摘要:最近上了,这是一个小巧的人脸检测库,行,大小,性能很好,效果也还还行。于是我想有没其他的能在浏览器跑的人脸检测库,一查才发现已经支持编译到,也就可以直接在浏览器里使用了。

最近picojs上了Github Trending,这是一个小巧的人脸检测库,200行JS,2K大小,性能很好,效果也还还行。于是我想有没其他的能在浏览器跑的人脸检测库,一查才发现OpenCV已经支持编译到WebAssembly,也就可以直接在浏览器里使用了。

编译OpenCV.js

安装Emscripten SDK:

git clone https://github.com/juj/emsdk.git
cd emsdk
./emsdk update-tags
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

Emscripten可以把C/C++程序编译成asm.js,然后通过binaryen的asm2wasm转成WebAssembly。

接着就可以编译OpenCV了:

wget https://github.com/opencv/opencv/archive/3.4.1.zip
unzip 3.4.1.zip
cd opencv-3.4.1
python ./platforms/js/build_js.py build_wasm --build_wasm

编译的成果在build_wasm/bin

$ ls -lh build_wasm/bin/
total 5.5M
-rw-r--r-- 1 lyp lyp 263K Apr 26 22:10 opencv.js
-rw-r--r-- 1 lyp lyp 262K Apr 26 22:10 opencv_js.js
-rw-r--r-- 1 lyp lyp 5.0M Apr 26 22:10 opencv_js.wasm

我们只需要其中的opencv.jsopencv_js.wasm,可以复制到其他地方使用,而opencv_js.js是中间生成的asm.js,可以忽略。

加载OpenCV

我们可以直接在HTML页面里引用opencv.js,它会自动加载opencv_js.wasm然后完成编译。遇到的第一个问题是,opencv.js默认会加载根目录的opencv_js.wasm,而我们通常会把js文件放在二级目录里。第二个问题是,我们的代码必须在OpenCV编译完成之后才能调用,不会代码就直接出错了。

更新2018-08-20:在Emscripten v1.38.9,locateFile行为已经修改,不需要这个hack了。

为了解决以上的问题,要通过Module进行配置:


Module是Emscripten生成的全局对象,通过它可以配置和调用Emscripten的API。例如locateFile用配置文件的实际URL。

preRun会在初始化前前调用,在这个时候,OpenCV还没初始化,我们可以先用Emscripten的文件系统API预加载之后会用的文件,这里我加载了一个预训练好的模型data/haarcascade_frontalface_default.xml,存放在Emscripten文件系统的"/face.xml"。

postRun会在初始化完成之后执行,这时候OpenCV编译完成,可以使用cv模块了。

获取摄像头图像

首先我们需要一个video标签,然后打开摄像头:

async function startCamera() {
    let video = document.getElementById("video");
    let stream = await navigator.mediaDevices.getUserMedia({
            video: {
                width: {
                    exact: videoWidth
                },
                height: {
                    exact: videoHeight
                }
            },
            audio: false
        })
    video.srcObject = stream;
    video.play();
}

然后我们就可以用cv.VideoCapture来读取摄像头了:

// 创建VideoCapture
let cap = new cv.VideoCapture(video);
// 创建存放图像的Mat
let src = new cv.Mat(videoHeight, videoWidth, cv.CV_8UC4);
// 读一帧图像
cap.read(src);
Haar Cascades人脸检测

创建人脸检测器:

faceCascade = new cv.CascadeClassifier();
faceCascade.load("face.xml")

接着就可以循环读取图像,检查人脸,显示了:

// Capture a frame
cap.read(src)

// Convert to greyscale
cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY);

// Downsample
let downSampled = new cv.Mat();
cv.pyrDown(gray, downSampled);
cv.pyrDown(downSampled, downSampled);

// Detect faces
let faces = new cv.RectVector();
faceCascade.detectMultiScale(downSampled, faces)

// Draw boxes
let size = downSampled.size();
let xRatio = videoWidth / size.width;
let yRatio = videoHeight / size.height;
for (let i = 0; i < faces.size(); ++i) {
    let face = faces.get(i);
    let point1 = new cv.Point(face.x * xRatio, face.y * yRatio);
    let point2 = new cv.Point((face.x + face.width) * xRatio, (face.y + face.height) * xRatio);
    cv.rectangle(src, point1, point2, [255, 0, 0, 255])
}

// Show image
cv.imshow(outputCanvas, src)

// Cleanup
downSampled.delete()
faces.delete()

性能在30FPS左右,效果要比picojs好,代价是需要加载很大的JS和wasm,初始化慢。

完整代码:learn_ml/opencv.js

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94673.html

相关文章

  • Python中使OpenCV进行人脸检测

    摘要:总结在本文中,我们学习了如何使用中的,即通过代码写了一个人脸检测的程序。 OpenCV是如今最流行的计算机视觉库,而我们今天就是要学习如何安装使用OpenCV,以及如何去访问我们的摄像头。然后我们一起来看看写一个人脸检测程序是如何地简单,简单到只需要几行代码。 在开始之前,我假设你已经对Python有一定的了解。当然,如果你觉得你还不够格,这里有推荐一些学习Python的电子书,你可以...

    stefanieliang 评论0 收藏0
  • 前端工程师做Face Detection

    摘要:身为一名前业务程序员和现前端程序员,这样的功能还是陌生的领域。需求使用加摄像头,通过人脸检测,完成自动拍照功能。在的屏幕上,显示摄像头的实时画面,要是画面中检测出人脸,则触发拍照。这样做的效果能够获得更高的,同时还能完成更远距离脸部的捕获。 因为项目原因,需要使用人脸检测(face detection)功能。身为一名前JAVA业务程序员和现前端程序员,这样的功能还是陌生的领域。那能不能...

    nodejh 评论0 收藏0
  • 机器视觉、模式识别库汇总

    摘要:十开放模式识别项目开放模式识别项目,致力于开发出一套包含图像处理计算机视觉自然语言处理模式识别机器学习和相关领域算法的函数库。 一、开源生物特征识别库 OpenBROpenBR 是一个用来从照片中识别人脸的工具。还支持推算性别与年龄。使用方法:$ br -algorithm FaceRecognition -compare me.jpg you.jpg二、计算机视觉库 OpenCVOpenC...

    habren 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<