├── README.md
├── index.html
├── index.js
├── model
└── haarcascade_frontalface_default.xml
├── opencv.js
└── opencv_js.wasm
/README.md:
--------------------------------------------------------------------------------
1 | # 使用OpenCV在前端进行人脸检测的实践
2 |
3 | ## 预览
4 |
5 | https://tidusinspira.github.io/opencv-wasm-example/
6 |
7 | ## 运行
8 |
9 | ```bash
10 | php -S 0.0.0.0:9999 或 放在nginx、apache等其他web服务器里运行
11 | ```
12 |
13 | ## 构建过程
14 |
15 | ### 安装Emscripten SDK
16 | ```bash
17 | git clone https://github.com/juj/emsdk.git
18 | cd emsdk
19 | ./emsdk install latest
20 | ./emsdk activate latest
21 | source ./emsdk_env.sh
22 | ```
23 |
24 | ### 获取OpenCV
25 | ```bash
26 | wget https://github.com/opencv/opencv/archive/3.4.1.zip
27 | unzip 3.4.1.zip
28 | cd opencv-3.4.1
29 | # 将OpenCV编译为WASM版本
30 | python ./platform/js/build_js.py build_wasm --build_wasm
31 |
32 | # 编译后的文件将生成在build_wasm/bin目录内,得到需要的opencv_js.wasm和opencv.js文件
33 | ```
34 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | let videoWidth = 640;
2 | let videoHeight = 480;
3 | let outputCanvas = document.createElement('canvas');
4 |
5 | let cap = null;
6 | let faceCascade = null;
7 | let src = null;
8 | let gray = null;
9 |
10 | navigator.getUserMedia =
11 | navigator.getUserMedia ||
12 | navigator.webkitGetUserMedia ||
13 | navigator.mozGetUserMedia ||
14 | navigator.msGetUserMeida;
15 |
16 | function run() {
17 | faceCascade = new cv.CascadeClassifier();
18 | faceCascade.load('face.xml');
19 |
20 | cap = new cv.VideoCapture(video);
21 | src = new cv.Mat(videoHeight, videoWidth, cv.CV_8UC4);
22 | gray = new cv.Mat(videoHeight, videoWidth, cv.CV_8UC1);
23 |
24 | startCamera();
25 | requestAnimationFrame(detectFace);
26 | }
27 |
28 | function startCamera() {
29 | navigator.getUserMedia(
30 | {
31 | video: true
32 | },
33 | function(stream) {
34 | video.srcObject = stream;
35 | video.play();
36 | },
37 | function(error) {
38 | console.error(error.name || error);
39 | }
40 | );
41 | }
42 |
43 | function saveImage(canvas, filename) {
44 | var image = canvas
45 | .toDataURL('image/png')
46 | .replace('image/png', 'image/octet-stream');
47 | let imgList = document.querySelector('#imgList');
48 | appendImage(image, imgList);
49 | }
50 |
51 | function appendImage(url, node) {
52 | var image = document.createElement('img');
53 | image.src = url;
54 | image.style.width = '100px';
55 | node.appendChild(image);
56 | }
57 |
58 | function detectFace() {
59 | // Capture a frame
60 | cap.read(src);
61 |
62 | // Convert to greyscale
63 | cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY);
64 |
65 | // Downsample
66 | let downSampled = new cv.Mat();
67 | cv.pyrDown(gray, downSampled);
68 | cv.pyrDown(downSampled, downSampled);
69 |
70 | // Detect faces
71 | let faces = new cv.RectVector();
72 | faceCascade.detectMultiScale(downSampled, faces);
73 |
74 | // Draw boxes
75 | let size = downSampled.size();
76 | let xRatio = videoWidth / size.width;
77 | let yRatio = videoHeight / size.height;
78 | for (let i = 0; i < faces.size(); ++i) {
79 | let face = faces.get(i);
80 | let point1 = new cv.Point(face.x * xRatio, face.y * yRatio);
81 | let point2 = new cv.Point(
82 | (face.x + face.width) * xRatio,
83 | (face.y + face.height) * xRatio
84 | );
85 | cv.rectangle(src, point1, point2, [255, 0, 0, 255]);
86 | saveImage(outputCanvas);
87 | }
88 | // Free memory
89 | downSampled.delete();
90 | faces.delete();
91 |
92 | // Show image
93 | cv.imshow(outputCanvas, src);
94 |
95 | requestAnimationFrame(detectFace);
96 | }
97 |
98 | // Config OpenCV
99 | var Module = {
100 | locateFile: function(name) {
101 | let files = {
102 | 'opencv_js.wasm': 'opencv_js.wasm'
103 | };
104 | return files[name];
105 | },
106 | preRun: [
107 | () => {
108 | Module.FS_createPreloadedFile(
109 | '/',
110 | 'face.xml',
111 | 'model/haarcascade_frontalface_default.xml',
112 | true,
113 | false
114 | );
115 | }
116 | ],
117 | postRun: [run]
118 | };
119 |
--------------------------------------------------------------------------------
/opencv_js.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TidusInSpira/opencv-wasm-example/0ec8fbec31dbd211d958ad795d0f862b134fca48/opencv_js.wasm
--------------------------------------------------------------------------------