Skip to content

Commit 2a9f390

Browse files
Merge pull request #413 from Leoqh96/master
feat: paddlejs-examples add facedecoration
2 parents 61716d9 + 593df18 commit 2a9f390

File tree

9 files changed

+271
-0
lines changed

9 files changed

+271
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[Chinese](./README_cn.md)
2+
3+
# faceDecoration
4+
5+
## Introduce
6+
7+
This directory is the code example of Bingdundun face decoration, which is implemented by using [@paddlejs-models/facedetect](https://www.npmjs.com/package/@paddlejs-models/facedetect) Paddle.js face detection SDK headgear effect.
8+
9+
## Setup
10+
11+
### **1. clone Paddle.js**
12+
```sh
13+
git clone https://github.com/PaddlePaddle/Paddle.js.git
14+
```
15+
16+
### **2. Enter the directory to install dependencies**
17+
```sh
18+
cd Paddle.js/packages/paddlejs-examples/faceDecoration && npm install
19+
```
20+
21+
## Performance
22+
23+
+ big-sized face
24+
<img width="800" src="https://mms-voice-fe.cdn.bcebos.com/pdmodel/face/detection/pic/bigsize.png"/>
25+
26+
+ small-sized face
27+
<img width="800" src="https://mms-voice-fe.cdn.bcebos.com/pdmodel/face/detection/pic/smallsize.png"/>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[英文版](./README.md)
2+
3+
# 头套生成器
4+
5+
## 介绍
6+
本目录为冰墩墩头套生成器代码示例,通过使用 [@paddlejs-models/facedetect](https://www.npmjs.com/package/@paddlejs-models/facedetect) Paddle.js 人脸检测 SDK实现头套效果。
7+
8+
## 项目启动
9+
10+
### **1. clone Paddle.js**
11+
```sh
12+
git clone https://github.com/PaddlePaddle/Paddle.js.git
13+
```
14+
15+
### **2. 进入 faceDecoration 目录,安装依赖**
16+
```sh
17+
cd Paddle.js/packages/paddlejs-examples/faceDecoration && npm install
18+
```
19+
20+
### 效果展示
21+
22+
+ 大尺寸大人脸效果
23+
<img width="800" src="https://mms-voice-fe.cdn.bcebos.com/pdmodel/face/detection/pic/bigsize.png"/>
24+
25+
+ 小尺寸人脸效果
26+
<img width="800" src="https://mms-voice-fe.cdn.bcebos.com/pdmodel/face/detection/pic/smallsize.png"/>
174 KB
Loading
133 KB
Loading
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>paddlejs mobilenet demo</title>
6+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
7+
<meta name="viewport" content="width=device-width, initial-scale=1">
8+
<style>
9+
.demo-nav {
10+
background-color: #2932e1;
11+
color: #fff;
12+
}
13+
.paddle-demo-card {
14+
margin-right: 0;
15+
margin-left: 0;
16+
background-color: #fff;
17+
}
18+
.infobox {
19+
background-color: #fff;
20+
border-radius: 6px;
21+
margin-bottom: 30px;
22+
padding: 20px;
23+
position: relative;
24+
min-height: 350px;
25+
box-sizing: border-box;
26+
color: #707070;
27+
}
28+
#loading {
29+
position: fixed;
30+
top: 0;
31+
left: 0;
32+
z-index: 10;
33+
width: 100vw;
34+
height: 100vh;
35+
line-height: 100vh;
36+
background-color: rgba(0, 0, 0, .4);
37+
color: #fff;
38+
text-align: center;
39+
font-size: 16px;
40+
}
41+
#resCanvas {
42+
margin-top: 2vw;
43+
}
44+
</style>
45+
</head>
46+
<body>
47+
<header class="navbar navbar-static-top bs-docs-nav demo-nav">
48+
<div class="container">
49+
<div class="navbar-header">
50+
<div class="navbar-brand">冰墩墩头套生成器</div>
51+
</div>
52+
</div>
53+
</header>
54+
<div class="container">
55+
<div class="col-xs-12">
56+
<div class="row">
57+
<div class="col-lg-3 col-md-6 col-sm-6 col-xs-12 continfobox">
58+
<div class="paddle-demo-card infobox text-center">
59+
<div class="h2">选择图片:</div>
60+
<input type="file" id="uploadImg">
61+
<canvas id="resCanvas" style="border: solid 3px red"></canvas>
62+
</div>
63+
</div>
64+
</div>
65+
</div>
66+
</div>
67+
<div id="loading">loading...</div>
68+
</body>
69+
</html>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { FaceDetector, createImage } from '@paddlejs-models/facedetect';
2+
3+
const resCanvas = document.getElementById('resCanvas') as HTMLCanvasElement;
4+
const resCtx = resCanvas.getContext('2d') as CanvasRenderingContext2D;
5+
const defaultImgPath = './img/multi_small_face.jpeg';
6+
const fileReader = new FileReader();
7+
const loading = document.getElementById('loading');
8+
const faceDetector = new FaceDetector();
9+
let faceDecoration = null as HTMLImageElement;
10+
11+
load();
12+
document.getElementById('uploadImg')!.onchange = function () {
13+
loadFile(this);
14+
};
15+
16+
async function load() {
17+
await faceDetector.init();
18+
faceDecoration = await createImage('./img/facedecoration.png');
19+
run(defaultImgPath);
20+
}
21+
22+
async function run(imgPath: string) {
23+
loading.style.display = 'block';
24+
const imgEle = await createImage(imgPath);
25+
drawImage(imgEle);
26+
// 预测
27+
const res = await faceDetector.detect(imgEle, { shrink: 0.4 });
28+
drawDecoration(res);
29+
loading.style.display = 'none';
30+
}
31+
32+
// 绘图
33+
function drawImage(img: HTMLImageElement) {
34+
const { naturalWidth, naturalHeight } = img;
35+
resCanvas.width = naturalWidth;
36+
resCanvas.height = naturalHeight;
37+
resCtx.drawImage(img, 0, 0, naturalWidth, naturalHeight);
38+
}
39+
40+
// 绘制头像框
41+
function drawDecoration(data) {
42+
// 按照人脸框面积排序 近大远小
43+
data.sort((item1, item2) => {
44+
return item1.width * item1.height - item2.width * item2.height;
45+
});
46+
47+
data.forEach(item => {
48+
resCtx.lineWidth = 4;
49+
// 人脸框位置
50+
const x = item.left * resCanvas.width;
51+
const y = item.top * resCanvas.height;
52+
const w = item.width * resCanvas.width;
53+
const h = item.height * resCanvas.height;
54+
55+
// 人脸装饰位置
56+
const ratio = 1.7;
57+
const decW = ratio * w;
58+
const decH = ratio * h;
59+
const decY = y - (decH - h) / 2;
60+
const decX = x - (decW - w) / 2;
61+
resCtx.drawImage(faceDecoration, decX, decY, decW, decH);
62+
});
63+
}
64+
65+
function loadFile(ipt) {
66+
if (!ipt.files || !ipt.files[0]) {
67+
return;
68+
}
69+
fileReader.onload = function (evt) {
70+
if (evt.target && typeof evt.target.result === 'string') {
71+
run(evt.target.result);
72+
}
73+
};
74+
fileReader.readAsDataURL(ipt.files[0]);
75+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "facedecoration",
3+
"version": "1.0.0",
4+
"description": "face decoration",
5+
"main": "index.js",
6+
"scripts": {
7+
"dev": "webpack-dev-server",
8+
"build": "webpack"
9+
},
10+
"author": "",
11+
"license": "ISC",
12+
"dependencies": {
13+
"@paddlejs-models/facedetect": "^1.0.3"
14+
},
15+
"devDependencies": {
16+
"html-webpack-plugin": "^3.2.0",
17+
"ts-loader": "^8.0.12",
18+
"typescript": "^3.9.5",
19+
"webpack": "^4.29.6",
20+
"webpack-cli": "^3.3.0",
21+
"webpack-dev-server": "^3.2.1"
22+
}
23+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": "../../../tsconfig",
3+
"include": [
4+
"index.ts"
5+
],
6+
"exclude": [
7+
"node_modules/"
8+
],
9+
"compilerOptions": {
10+
"outDir": "dist",
11+
"types": ["jest", "node"]
12+
}
13+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const path = require('path');
2+
const HtmlWebpackPlugin = require('html-webpack-plugin');
3+
4+
module.exports = {
5+
mode: 'development',
6+
devtool: 'inline-source-map',
7+
entry: './index.ts',
8+
devServer: {
9+
hot: true,
10+
host: '0.0.0.0',
11+
port: 9003,
12+
open: true
13+
},
14+
plugins: [
15+
new HtmlWebpackPlugin({
16+
template: './index.html',
17+
inject: 'body',
18+
filename: 'index.html'
19+
})
20+
],
21+
resolve: {
22+
// Add ".ts" and ".tsx" as resolvable extensions.
23+
extensions: ['.ts', '.js']
24+
},
25+
module: {
26+
rules: [
27+
{
28+
test: /\.ts$/,
29+
loader: 'ts-loader',
30+
exclude: /node_modules/
31+
}
32+
]
33+
},
34+
output: {
35+
filename: '[name].js',
36+
path: path.resolve(__dirname, 'dist')
37+
}
38+
};

0 commit comments

Comments
 (0)