├── .gitignore
├── README.md
├── assets
├── avg_v1.0.png
├── avg_v1.1.png
└── avg_v2.0.gif
├── bfm_visual_tool.sln
└── bfm_visual_tool
├── MainWindow.cpp
├── MainWindow.h
├── MainWindow.qrc
├── MainWindow.ui
├── OpenGLWidget.cpp
├── OpenGLWidget.h
├── Resources
└── bfm_tool.ico
├── bfm.cpp
├── bfm.h
├── bfm_tool.rc
├── bfm_visual_tool.vcxproj
├── bfm_visual_tool.vcxproj.filters
├── bfm_visual_tool.vcxproj.user
├── constant.h
├── data.h
├── inputs-2017.txt
├── inputs.txt
├── main.cpp
├── random.cpp
├── random.h
└── vec.h
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | bfm_visual_tool/GeneratedFiles
3 |
4 | bfm_visual_tool/x64
5 |
6 | x64
7 |
8 | *.ply
9 |
10 | .vs
11 | *.bin
12 | bfm_visual_tool/data/data.zip
13 | *.h5
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BFM模型可视化工具 - C++
2 |
3 | 通过C++和Qt5构建的一个Basel人脸模型(Basel Face Model, BFM)的可视化工具。
4 |
5 |
6 |
7 |
8 |
9 | ## 功能介绍
10 |
11 | ### 生成随机人脸
12 |
13 | 设置`random range` 后的滑动条,可以调节随机程度(正态分布的方差),0.0时为平均脸。
14 |
15 | 设置完成之后点击下方按钮即可在左侧生成随机人脸。
16 |
17 | ### 设置PC权重
18 |
19 | 可以修改面部Shape、Texture和Expr的PC权重,BFM共有199个PC可以在左侧下拉栏中选择,右测滑动条调节数值大小,调节完成后点击对应的按钮完成设置。
20 |
21 | *[NOTE] 修改PC权重需要在已经生成人脸的前提下使用*
22 |
23 | ### 将生成人脸存储到文件
24 |
25 | 目前支持的文件格式仅有PLY格式,可以通过MeshLab打开进行查看。
26 |
27 |
28 |
29 | ## 其他功能
30 |
31 | ### 预然人脸操作
32 |
33 | 该部分通过Qt5内置OpenGL实现,支持按键如下:
34 |
35 | * 鼠标左键:长按后可以拖拉旋转人脸;
36 | * 鼠标滚轮:缩放;
37 | * 键盘A/W/S/D:向左转/放大/向右转/缩小。
38 |
39 |
--------------------------------------------------------------------------------
/assets/avg_v1.0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bemfool/bfm-visual-tool/032d8b7629c497d7c3b4edef997a24008a8b3031/assets/avg_v1.0.png
--------------------------------------------------------------------------------
/assets/avg_v1.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bemfool/bfm-visual-tool/032d8b7629c497d7c3b4edef997a24008a8b3031/assets/avg_v1.1.png
--------------------------------------------------------------------------------
/assets/avg_v2.0.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bemfool/bfm-visual-tool/032d8b7629c497d7c3b4edef997a24008a8b3031/assets/avg_v2.0.gif
--------------------------------------------------------------------------------
/bfm_visual_tool.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2026
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bfm_visual_tool", "bfm_visual_tool\bfm_visual_tool.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.ActiveCfg = Debug|x64
15 | {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.Build.0 = Debug|x64
16 | {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|x64
17 | {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.Build.0 = Release|x64
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {2D3C74E0-D3D8-471B-A33A-DFAF1B53A3D3}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/bfm_visual_tool/MainWindow.cpp:
--------------------------------------------------------------------------------
1 | #include "MainWindow.h"
2 |
3 | const double SHAPE_SCALE = 0.1;
4 | const double TEX_SCALE = 120;
5 | const double EXPR_SCALE = 0.3;
6 |
7 | MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
8 | {
9 | ui.setupUi(this);
10 | statusBar()->showMessage("loading...", 3000);
11 | model.init("inputs.txt");
12 | initUI();
13 | initSignalSlots();
14 | setWindowTitle("Tools for Basel Face Model");
15 | statusBar()->showMessage("ready");
16 | }
17 |
18 | void MainWindow::initUI()
19 | {
20 | genRndFaceBtn = ui.centralWidget->findChild("genRndFaceBtn");
21 | savePlyBtn = ui.centralWidget->findChild("savePlyBtn");
22 | setShapePcBtn = ui.centralWidget->findChild("setShapePcBtn");
23 | setTexPcBtn = ui.centralWidget->findChild("setTexPcBtn");
24 | setExprPcBtn = ui.centralWidget->findChild("setExprPcBtn");
25 |
26 | rndRangeSlider = ui.centralWidget->findChild("rndRangeSlider");
27 | shapeSlider = ui.centralWidget->findChild("shapeSlider");
28 | texSlider = ui.centralWidget->findChild("texSlider");
29 | exprSlider = ui.centralWidget->findChild("exprSlider");
30 |
31 | shapeComboBox = ui.centralWidget->findChild("shapeComboBox");
32 | texComboBox = ui.centralWidget->findChild("texComboBox");
33 | exprComboBox = ui.centralWidget->findChild("exprComboBox");
34 | for (int i = 1; i <= model.get_n_id_pc(); i++) {
35 | shapeComboBox->addItem(QString::number(i));
36 | texComboBox->addItem(QString::number(i));
37 | }
38 | for (int i = 1; i <= model.get_n_expr_pc(); i++)
39 | exprComboBox->addItem(QString::number(i));
40 |
41 | saveFilename = ui.centralWidget->findChild("saveFilename");
42 | openGLWidget = ui.centralWidget->findChild("openGLWidget");
43 | qDebug() << "[viewer] ui init done.\n";
44 | }
45 |
46 | void MainWindow::initSignalSlots()
47 | {
48 | QObject::connect(genRndFaceBtn, SIGNAL(clicked()), this, SLOT(generateRandomFace()));
49 | QObject::connect(setShapePcBtn, SIGNAL(clicked()), this, SLOT(setShapePc()));
50 | QObject::connect(setTexPcBtn, SIGNAL(clicked()), this, SLOT(setTexPc()));
51 | QObject::connect(setExprPcBtn, SIGNAL(clicked()), this, SLOT(setExprPc()));
52 |
53 | QObject::connect(shapeComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(synShapeSlider()));
54 | QObject::connect(texComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(synTexSlider()));
55 | QObject::connect(exprComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(synExprSlider()));
56 |
57 | QObject::connect(savePlyBtn, SIGNAL(clicked()), this, SLOT(savePly()));
58 | }
59 |
60 | void MainWindow::generateRandomFace()
61 | {
62 | statusBar()->showMessage("generating...", 3000);
63 | double sliderVal = (double)rndRangeSlider->value();
64 | model.generate_random_face(sliderVal / SHAPE_SCALE, sliderVal / TEX_SCALE, sliderVal / EXPR_SCALE);
65 | openGLWidget->theta = 0.0;
66 | openGLWidget->scale = 1.0;
67 | openGLWidget->update();
68 | synShapeSlider();
69 | synTexSlider();
70 | synExprSlider();
71 | }
72 |
73 | void MainWindow::synShapeSlider()
74 | {
75 | int pc = shapeComboBox->currentIndex();
76 | shapeSlider->setValue(int(model.get_mutable_shape_coef()(pc) * SHAPE_SCALE));
77 | }
78 |
79 |
80 | void MainWindow::synTexSlider()
81 | {
82 | int pc = texComboBox->currentIndex();
83 | texSlider->setValue(int(model.get_mutable_tex_coef()(pc) * TEX_SCALE));
84 | }
85 |
86 | void MainWindow::synExprSlider()
87 | {
88 | int pc = exprComboBox->currentIndex();
89 | exprSlider->setValue(int(model.get_mutable_expr_coef()(pc) * EXPR_SCALE));
90 | }
91 |
92 |
93 | void MainWindow::setShapePc()
94 | {
95 | int pc = shapeComboBox->currentIndex();
96 | double pcValue = shapeSlider->value() / SHAPE_SCALE;
97 | model.get_mutable_shape_coef()(pc) = pcValue;
98 | model.generate_face();
99 | openGLWidget->update();
100 | }
101 |
102 | void MainWindow::setTexPc()
103 | {
104 | int pc = texComboBox->currentIndex();
105 | double pcValue = texSlider->value() / TEX_SCALE;
106 | model.get_mutable_tex_coef()(pc) = pcValue;
107 | model.generate_face();
108 | openGLWidget->update();
109 | }
110 |
111 | void MainWindow::setExprPc()
112 | {
113 | int pc = exprComboBox->currentIndex();
114 | double pcValue = exprSlider->value() / EXPR_SCALE;
115 | model.get_mutable_expr_coef()(pc) = pcValue;
116 | model.generate_face();
117 | openGLWidget->update();
118 | }
119 |
120 | void MainWindow::savePly()
121 | {
122 | std::string filename = saveFilename->toPlainText().toStdString();
123 |
124 | /* Make sure filename is like *.ply format (default filename = rnd_face.ply) */
125 | int fSize = filename.size();
126 | if (fSize == 0)
127 | filename = "rnd_face.ply";
128 | else if (fSize <= 4 || filename.substr(fSize - 4) != ".ply")
129 | filename = filename + ".ply";
130 |
131 | model.ply_write(filename);
132 | QDialog *dialog = new QDialog;
133 | dialog->setModal(true);
134 | dialog->resize(300, 100);
135 | QLabel *label = new QLabel(dialog);
136 | label->setText("save - success");
137 | dialog->exec();
138 | }
139 |
140 | void MainWindow::keyPressEvent(QKeyEvent *event) {
141 | switch (event->key()) {
142 | case Qt::Key_A:
143 | openGLWidget->theta += 0.1;
144 | break;
145 | case Qt::Key_D:
146 | openGLWidget->theta -= 0.1;
147 | break;
148 | case Qt::Key_W:
149 | openGLWidget->scale += 0.1;
150 | break;
151 | case Qt::Key_S:
152 | openGLWidget->scale -= 0.1;
153 | break;
154 | default:
155 | break;
156 | }
157 | openGLWidget->update();
158 | }
159 |
160 |
161 | void MainWindow::wheelEvent(QWheelEvent *event) {
162 | openGLWidget->scale += event->delta() / 1200.0;
163 | if (openGLWidget->scale <= 0.0)
164 | openGLWidget->scale = 0.01;
165 | openGLWidget->update();
166 | }
--------------------------------------------------------------------------------
/bfm_visual_tool/MainWindow.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | /*********************************************************************
3 |
4 | Author: Bemfoo
5 | Date: 2019-10-26
6 | Description: The main widget window of Basel face model visual tool.
7 |
8 | **********************************************************************/
9 |
10 | #include
11 | #include "ui_MainWindow.h"
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include "OpenGLWidget.h"
19 | #include
20 | #include "bfm.h"
21 |
22 | class QSlider;
23 | class QPushButton;
24 | class QLabel;
25 | class QComboBox;
26 | class QOpenGLWidget;
27 | class QKeyEvent;
28 | class QWheelEvent;
29 | class QDialog;
30 |
31 | class MainWindow : public QMainWindow
32 | {
33 | Q_OBJECT
34 |
35 | public:
36 | MainWindow(QWidget *parent = Q_NULLPTR);
37 | bfm &getModel() { return model; }
38 | void keyPressEvent(QKeyEvent *event);
39 | void wheelEvent(QWheelEvent *event);
40 |
41 | private slots:
42 | void generateRandomFace();
43 | void synShapeSlider();
44 | void synTexSlider();
45 | void synExprSlider();
46 | void setShapePc();
47 | void setTexPc();
48 | void setExprPc();
49 | void savePly();
50 |
51 | private:
52 | Ui::MainWindowClass ui;
53 |
54 | bfm model;
55 |
56 | OpenGLWidget *openGLWidget;
57 | QPushButton *genRndFaceBtn;
58 | QPushButton *savePlyBtn;
59 | QPushButton *setShapePcBtn;
60 | QPushButton *setTexPcBtn;
61 | QPushButton *setExprPcBtn;
62 |
63 | QSlider *shapeSlider;
64 | QSlider *texSlider;
65 | QSlider *exprSlider;
66 | QSlider *rndRangeSlider;
67 |
68 | QComboBox *shapeComboBox;
69 | QComboBox *texComboBox;
70 | QComboBox *exprComboBox;
71 |
72 | QTextEdit *saveFilename;
73 |
74 | void initUI();
75 | void initSignalSlots();
76 | };
77 |
--------------------------------------------------------------------------------
/bfm_visual_tool/MainWindow.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/bfm_visual_tool/MainWindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindowClass
4 |
5 |
6 |
7 | 0
8 | 0
9 | 1025
10 | 709
11 |
12 |
13 |
14 | QtTest
15 |
16 |
17 |
18 |
19 |
20 | 580
21 | 80
22 | 421
23 | 28
24 |
25 |
26 |
27 | generate random face
28 |
29 |
30 |
31 |
32 |
33 | 20
34 | 20
35 | 531
36 | 651
37 |
38 |
39 |
40 |
41 |
42 |
43 | 580
44 | 30
45 | 421
46 | 41
47 |
48 |
49 |
50 | -
51 |
52 |
53 | random range
54 |
55 |
56 |
57 | -
58 |
59 |
60 |
61 |
62 |
63 |
64 | -
65 |
66 |
67 | 0
68 |
69 |
70 | 200
71 |
72 |
73 | 2
74 |
75 |
76 | Qt::Horizontal
77 |
78 |
79 |
80 | -
81 |
82 |
83 | max
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | 580
93 | 140
94 | 421
95 | 41
96 |
97 |
98 |
99 | -
100 |
101 |
102 | No.
103 |
104 |
105 |
106 | -
107 |
108 |
109 | -
110 |
111 |
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -1000
120 |
121 |
122 | 1000
123 |
124 |
125 | Qt::Horizontal
126 |
127 |
128 |
129 | -
130 |
131 |
132 | max
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | 580
142 | 190
143 | 421
144 | 28
145 |
146 |
147 |
148 | set shape PC
149 |
150 |
151 |
152 |
153 |
154 | 580
155 | 120
156 | 421
157 | 16
158 |
159 |
160 |
161 | =================== shape PC =======================
162 |
163 |
164 |
165 |
166 |
167 | 580
168 | 300
169 | 421
170 | 28
171 |
172 |
173 |
174 | set texture PC
175 |
176 |
177 |
178 |
179 |
180 | 580
181 | 250
182 | 421
183 | 41
184 |
185 |
186 |
187 | -
188 |
189 |
190 | No.
191 |
192 |
193 |
194 | -
195 |
196 |
197 | -
198 |
199 |
200 |
201 |
202 |
203 |
204 | -
205 |
206 |
207 | -1000
208 |
209 |
210 | 1000
211 |
212 |
213 | Qt::Horizontal
214 |
215 |
216 |
217 | -
218 |
219 |
220 | max
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 | 580
230 | 230
231 | 421
232 | 16
233 |
234 |
235 |
236 | =================== texture PC =======================
237 |
238 |
239 |
240 |
241 |
242 | 580
243 | 620
244 | 421
245 | 31
246 |
247 |
248 |
249 |
250 | QLayout::SetFixedSize
251 |
252 | -
253 |
254 |
255 | filename:
256 |
257 |
258 |
259 | -
260 |
261 |
262 |
263 | 236
264 | 29
265 |
266 |
267 |
268 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
269 | <html><head><meta name="qrichtext" content="1" /><style type="text/css">
270 | p, li { white-space: pre-wrap; }
271 | </style></head><body style=" font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;">
272 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'SimSun';">rnd_face.ply</span></p></body></html>
273 |
274 |
275 |
276 | -
277 |
278 |
279 | save as PLY
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 | 580
289 | 340
290 | 421
291 | 16
292 |
293 |
294 |
295 | =============== == expression PC =======================
296 |
297 |
298 |
299 |
300 |
301 | 580
302 | 360
303 | 421
304 | 41
305 |
306 |
307 |
308 | -
309 |
310 |
311 | No.
312 |
313 |
314 |
315 | -
316 |
317 |
318 | -
319 |
320 |
321 |
322 |
323 |
324 |
325 | -
326 |
327 |
328 | -1000
329 |
330 |
331 | 1000
332 |
333 |
334 | Qt::Horizontal
335 |
336 |
337 |
338 | -
339 |
340 |
341 | max
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 | 580
351 | 410
352 | 421
353 | 28
354 |
355 |
356 |
357 | set texture PC
358 |
359 |
360 |
361 |
362 |
387 |
388 |
389 | 载入模型
390 |
391 |
392 |
393 |
394 | 更换模型
395 |
396 |
397 |
398 |
399 | BFM模型预处理
400 |
401 |
402 |
403 |
404 |
405 |
406 | OpenGLWidget
407 | QOpenGLWidget
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
--------------------------------------------------------------------------------
/bfm_visual_tool/OpenGLWidget.cpp:
--------------------------------------------------------------------------------
1 | #include "OpenGLWidget.h"
2 | #include "MainWindow.h"
3 |
4 | OpenGLWidget::OpenGLWidget(QWidget *parent) : QOpenGLWidget(parent) {}
5 |
6 |
7 | void OpenGLWidget::initializeGL()
8 | {
9 | initializeOpenGLFunctions();
10 | glClearColor(0, 0, 0, 1);
11 | glEnable(GL_DEPTH_TEST);
12 | glEnable(GL_LIGHT0);
13 | glEnable(GL_LIGHTING);
14 | glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
15 | glEnable(GL_COLOR_MATERIAL);
16 | glLoadIdentity();
17 | gluLookAt(0, 0, 300000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
18 | }
19 |
20 |
21 | void OpenGLWidget::resizeGL(int width, int height)
22 | {
23 | glViewport(0, 0, width, height);
24 | glMatrixMode(GL_PROJECTION);
25 | glLoadIdentity();
26 | gluPerspective(60.0, (GLfloat)width / (GLfloat)height, 1.0, 600000.0);
27 | glMatrixMode(GL_MODELVIEW);
28 | glLoadIdentity();
29 | gluLookAt(0, 0, 300000.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
30 | }
31 |
32 |
33 | void OpenGLWidget::paintGL()
34 | {
35 | MainWindow *p = (MainWindow*)(parentWidget()->parentWidget());
36 | shape = p->getModel().get_current_blendshape();
37 | tex = p->getModel().get_current_tex();
38 | tl = p->getModel().get_tl();
39 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
40 | if (shape.nr()!=0) {
41 | /* human face model */
42 | double sint = sin(theta), cost = cos(theta);
43 | for (int i = 0; i < tl.size()/3; i++) {
44 | glBegin(GL_TRIANGLES);
45 | double xIdx = tl(i * 3) - 1;
46 | double yIdx = tl(i * 3 + 1) - 1;
47 | double zIdx = tl(i * 3 + 2) - 1;
48 | glColor3f(tex(xIdx * 3) / 255.0, tex(xIdx * 3 + 1) / 255.0, tex(xIdx * 3 + 2) / 255.0);
49 | glVertex3f(shape(xIdx * 3) * scale * cost - shape(xIdx * 3 + 2) * scale * sint, shape(xIdx * 3 + 1) * scale, shape(xIdx * 3) * scale * sint + shape(xIdx * 3 + 2) * scale * cost);
50 | glColor3f(tex(yIdx * 3) / 255.0, tex(yIdx * 3 + 1) / 255.0, tex(yIdx * 3 + 2) / 255.0);
51 | glVertex3f(shape(yIdx * 3) * scale * cost - shape(yIdx * 3 + 2) * scale * sint, shape(yIdx * 3 + 1) * scale, shape(yIdx * 3) * scale * sint + shape(yIdx * 3 + 2) * scale * cost);
52 | glColor3f(tex(zIdx * 3) / 255.0, tex(zIdx * 3 + 1) / 255.0, tex(zIdx * 3 + 2) / 255.0);
53 | glVertex3f(shape(zIdx * 3) * scale * cost - shape(zIdx * 3 + 2) * scale * sint, shape(zIdx * 3 + 1) * scale, shape(zIdx * 3) * scale * sint + shape(zIdx * 3 + 2) * scale * cost);
54 | glEnd();
55 | }
56 | }
57 | else {
58 | /* initial scene - triangle */
59 | glBegin(GL_TRIANGLES);
60 | glColor3f(1.0, 0.0, 0.0);
61 | glVertex3f(-50000 * cos(theta) * scale, 0, 0);
62 | glColor3f(0.0, 1.0, 0.0);
63 | glVertex3f(50000 * cos(theta) * scale, 0, 0);
64 | glColor3f(0.0, 0.0, 1.0);
65 | glVertex3f(0.0, 50000 * scale, 0);
66 | glEnd();
67 | }
68 | }
69 |
70 |
71 | void OpenGLWidget::mousePressEvent(QMouseEvent *event)
72 | {
73 | if (event->button() == Qt::LeftButton)
74 | oldX = event->x(); /* record the current X pos */
75 | }
76 |
77 |
78 | void OpenGLWidget::mouseMoveEvent(QMouseEvent *event)
79 | {
80 | if (event->buttons() & Qt::LeftButton) {
81 | double clockwise;
82 | if (event->x() < oldX)
83 | clockwise = -1.0;
84 | else if (event->x() > oldX)
85 | clockwise = 1.0;
86 | else
87 | clockwise = 0;
88 | oldX = event->x();
89 | theta += clockwise * 0.1;
90 | update();
91 | }
92 | }
--------------------------------------------------------------------------------
/bfm_visual_tool/OpenGLWidget.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | /*********************************************************************
3 |
4 | Author: Bemfoo
5 | Date: 2019-10-26
6 | Description: A Qt5 widget implemented by built-in OpenGL to show Basel
7 | face model.
8 |
9 | **********************************************************************/
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | class QMouseEvent;
20 | class QKeyEvent;
21 |
22 | /*
23 | * Class: OpenGLWidget
24 | * --------------------------------------------------------------------
25 | * The widget is used to show generated face.
26 | */
27 | class OpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
28 | {
29 | Q_OBJECT
30 |
31 | public:
32 | explicit OpenGLWidget(QWidget *parent = Q_NULLPTR);
33 |
34 | public:
35 | void initializeGL() Q_DECL_OVERRIDE;
36 | void paintGL() Q_DECL_OVERRIDE;
37 | void resizeGL(int w, int h) Q_DECL_OVERRIDE;
38 |
39 |
40 | /*
41 | * Function: mouseMoveEvent
42 | * ------------------------------------------------------------
43 | * When mouse move, rotate model in the direction judged by the
44 | * relative position between current X and oldX.
45 | */
46 |
47 | void mouseMoveEvent(QMouseEvent *event);
48 |
49 |
50 | /*
51 | * Function: mousePressEvent
52 | * -------------------------------------------------------------
53 | * When mouse clicks, mark current X pos as oldX.
54 | */
55 |
56 | void mousePressEvent(QMouseEvent *event);
57 |
58 | public:
59 | double oldX; /* last position of mouse, used for rotation */
60 | double theta = 0.0; /* rotation degree */
61 | double scale = 1.0; /* zooming scale */
62 |
63 | dlib::matrix shape;
64 | dlib::matrix tex;
65 | dlib::matrix tl;
66 | };
67 |
--------------------------------------------------------------------------------
/bfm_visual_tool/Resources/bfm_tool.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bemfool/bfm-visual-tool/032d8b7629c497d7c3b4edef997a24008a8b3031/bfm_visual_tool/Resources/bfm_tool.ico
--------------------------------------------------------------------------------
/bfm_visual_tool/bfm.cpp:
--------------------------------------------------------------------------------
1 | #include "bfm.h"
2 |
3 | bfm::bfm(const std::string &filename) {
4 | init(filename);
5 | }
6 |
7 |
8 | void bfm::init(const std::string &filename) {
9 | if (!read_parm_from_file(filename))
10 | return;
11 | init_parm();
12 | load_data();
13 | }
14 |
15 |
16 | void bfm::data_check() {
17 | bfm_out << "check data\n";
18 | bfm_out << " (1) shape mu: \n";
19 | bfm_out << " Yours: " << shape_mu(0, 0) << "\n";
20 | bfm_out << " Correct: -57239 42966 80410\n\n";
21 | bfm_out << " (2) shape ev: \n";
22 | bfm_out << " Yours: " << shape_ev(0, 0) << " " << shape_ev(1, 0) << "\n";
23 | bfm_out << " Correct: 884340 555880\n\n";
24 | bfm_out << " (3) shape pc: \n";
25 | bfm_out << " Yours: " << shape_pc(0, 0) << "\n";
26 | bfm_out << " Correct: -0.0024\n\n";
27 | bfm_out << " (4) texture mu: \n";
28 | bfm_out << " Yours: " << tex_mu(0, 0) << endl;
29 | bfm_out << " Correct: 182.8750 135.0400 107.1400\n" << endl;
30 | bfm_out << " (5) texture ev: \n";
31 | bfm_out << " Yours: " << tex_ev(0) << " " << tex_ev(1) << "\n";
32 | bfm_out << " Correct: 4103.2 2024.1\n\n";
33 | bfm_out << " (6) texture pc: \n";
34 | bfm_out << " Yours: " << tex_pc(0, 0) << "\n";
35 | bfm_out << " Correct: -0.0028\n\n";
36 | bfm_out << " (7) expression mu: \n";
37 | bfm_out << " Yours: " << expr_mu(0, 0) << endl;
38 | bfm_out << " Correct: 182.8750 135.0400 107.1400\n" << endl;
39 | bfm_out << " (8) expression ev: \n";
40 | bfm_out << " Yours: " << expr_ev(0) << " " << expr_ev(1) << "\n";
41 | bfm_out << " Correct: 4103.2 2024.1\n\n";
42 | bfm_out << " (9) expression pc: \n";
43 | bfm_out << " Yours: " << expr_pc(0, 0) << "\n";
44 | bfm_out << " Correct: -0.0028\n\n";
45 | bfm_out << " (10) triangle list: \n";
46 | bfm_out << " Yours: " << tl(0) << " " << tl(1) << "\n";
47 | bfm_out << " Correct: -0.0028\n\n";
48 | }
49 |
50 |
51 | bool bfm::read_parm_from_file(const std::string &filename) {
52 | ifstream in(filename, std::ios::in);
53 | if (!in) {
54 | bfm_out << "[ERROR] Can't open " << filename.c_str() << ".\n";
55 | return false;
56 | }
57 | in >> bfm_h5_path;
58 | in >> n_vertice >> n_face >> n_id_pc >> n_expr_pc;
59 | in >> n_landmark >> landmark_idx_path;
60 | in >> intrinsic_parm[0] >> intrinsic_parm[1] >> intrinsic_parm[2] >> intrinsic_parm[3];
61 | in >> shape_mu_h5_path >> shape_ev_h5_path >> shape_pc_h5_path;
62 | in >> tex_mu_h5_path >> tex_ev_h5_path >> tex_pc_h5_path;
63 | in >> expr_mu_h5_path >> expr_ev_h5_path >> expr_pc_h5_path;
64 | in >> tl_h5_path;
65 |
66 | in.close();
67 | return true;
68 | }
69 |
70 |
71 | void bfm::init_parm() {
72 | shape_coef.set_size(n_id_pc, 1);
73 | shape_mu.set_size(n_vertice * 3, 1);
74 | shape_ev.set_size(n_id_pc, 1);
75 | shape_pc.set_size(n_vertice * 3, n_id_pc);
76 |
77 | tex_coef.set_size(n_id_pc, 1);
78 | tex_mu.set_size(n_vertice * 3, 1);
79 | tex_ev.set_size(n_id_pc, 1);
80 | tex_pc.set_size(n_vertice * 3, n_id_pc);
81 |
82 | expr_coef.set_size(n_expr_pc, 1);
83 | expr_mu.set_size(n_vertice * 3, 1);
84 | expr_ev.set_size(n_expr_pc, 1);
85 | expr_pc.set_size(n_vertice * 3, n_expr_pc);
86 |
87 | tl.set_size(n_face * 3, 1);
88 |
89 | current_shape.set_size(n_vertice * 3, 1);
90 | current_tex.set_size(n_vertice * 3, 1);
91 | current_expr.set_size(n_vertice * 3, 1);
92 | current_blendshape.set_size(n_vertice * 3, 1);
93 |
94 | landmark_idx.resize(n_landmark);
95 | }
96 |
97 |
98 | bool bfm::load_data() {
99 | float *shape_mu_raw = new float[n_vertice * 3];
100 | float *shape_ev_raw = new float[n_id_pc];
101 | float *shape_pc_raw = new float[n_vertice * 3 * n_id_pc];
102 | float *tex_mu_raw = new float[n_vertice * 3];
103 | float *tex_ev_raw = new float[n_id_pc];
104 | float *tex_pc_raw = new float[n_vertice * 3 * n_id_pc];
105 | float *expr_mu_raw = new float[n_vertice * 3];
106 | float *expr_ev_raw = new float[n_expr_pc];
107 | float *expr_pc_raw = new float[n_vertice * 3 * n_expr_pc];
108 | unsigned int *tl_raw = new unsigned int[n_face * 3];
109 |
110 | H5File file(bfm_h5_path, H5F_ACC_RDONLY);
111 | load_hdf5_model(shape_mu, shape_mu_h5_path, PredType::NATIVE_FLOAT);
112 | load_hdf5_model(shape_ev, shape_ev_h5_path, PredType::NATIVE_FLOAT);
113 | load_hdf5_model(shape_pc, shape_pc_h5_path, PredType::NATIVE_FLOAT);
114 |
115 | load_hdf5_model(tex_mu, tex_mu_h5_path, PredType::NATIVE_FLOAT);
116 | load_hdf5_model(tex_ev, tex_ev_h5_path, PredType::NATIVE_FLOAT);
117 | load_hdf5_model(tex_pc, tex_pc_h5_path, PredType::NATIVE_FLOAT);
118 |
119 | load_hdf5_model(expr_mu, expr_mu_h5_path, PredType::NATIVE_FLOAT);
120 | load_hdf5_model(expr_ev, expr_ev_h5_path, PredType::NATIVE_FLOAT);
121 | load_hdf5_model(expr_pc, expr_pc_h5_path, PredType::NATIVE_FLOAT);
122 |
123 | load_hdf5_model(tl, tl_h5_path, PredType::NATIVE_UINT32);
124 | file.close();
125 |
126 | shape_mu = shape_mu * 1000.0;
127 |
128 | ifstream in(landmark_idx_path, std::ios::in);
129 | if (!in) {
130 | bfm_out << "[ERROR] Can't open " << landmark_idx_path.c_str() << ".\n";
131 | return false;
132 | }
133 | for (int i = 0; i < n_landmark; i++) {
134 | int tmp_idx;
135 | in >> tmp_idx;
136 | landmark_idx[i] = tmp_idx - 1;
137 | }
138 | bfm_out << "[bfm] load data - success.\n";
139 | return true;
140 | }
141 |
142 |
143 | void bfm::generate_random_face(double scale) {
144 | shape_coef = randn(n_id_pc, scale);
145 | tex_coef = randn(n_id_pc, scale);
146 | expr_coef = randn(n_expr_pc, scale);
147 | generate_face();
148 | }
149 |
150 |
151 | void bfm::generate_random_face(double shape_scale, double tex_scale, double expr_scale) {
152 | shape_coef = randn(n_id_pc, shape_scale);
153 | tex_coef = randn(n_id_pc, tex_scale);
154 | expr_coef = randn(n_expr_pc, expr_scale);
155 | generate_face();
156 | }
157 |
158 |
159 | void bfm::generate_face() {
160 | current_shape = coef2object(shape_coef, shape_mu, shape_pc, shape_ev);
161 | current_tex = coef2object(tex_coef, tex_mu, tex_pc, tex_ev);
162 | current_expr = coef2object(expr_coef, expr_mu, expr_pc, expr_ev);
163 | current_blendshape = current_shape + current_expr;
164 | }
165 |
166 |
167 | dlib::matrix bfm::coef2object(dlib::matrix &coef, dlib::matrix &mu,
168 | dlib::matrix &pc, dlib::matrix &ev) {
169 | return mu + pc * pointwise_multiply(coef, ev);
170 | }
171 |
172 |
173 | void bfm::ply_write(string fn, bool pick_landmark) {
174 | ofstream out;
175 | /* Note: In Linux Cpp, we should use std::ios::bfm_out as flag, which is not necessary in Windows */
176 | out.open(fn, std::ios::out | std::ios::binary);
177 | if (!out) {
178 | bfm_out << "Creation of " << fn.c_str() << " failed.\n";
179 | return;
180 | }
181 | out << "ply\n";
182 | out << "format binary_little_endian 1.0\n";
183 | out << "comment Made from the 3D Morphable Face Model of the Univeristy of Basel, Switzerland.\n";
184 | out << "element vertex " << n_vertice << "\n";
185 | out << "property float x\n";
186 | out << "property float y\n";
187 | out << "property float z\n";
188 | out << "property uchar red\n";
189 | out << "property uchar green\n";
190 | out << "property uchar blue\n";
191 | out << "element face " << n_face << "\n";
192 | out << "property list uchar int vertex_indices\n";
193 | out << "end_header\n";
194 |
195 | int cnt = 0;
196 | for (int i = 0; i < 68; i++)
197 | std::cout << " " << landmark_idx[i] << std::endl;
198 |
199 | for (int i = 0; i < n_vertice; i++) {
200 | float x = float(current_blendshape(i * 3));
201 | float y = float(current_blendshape(i * 3 + 1));
202 | float z = float(current_blendshape(i * 3 + 2));
203 | unsigned char r, g, b;
204 | if (find(landmark_idx.begin(), landmark_idx.end(), i) != landmark_idx.end()) {
205 | r = 255;
206 | g = 0;
207 | b = 0;
208 | cnt++;
209 | }
210 | else {
211 | r = current_tex(i * 3);
212 | g = current_tex(i * 3 + 1);
213 | b = current_tex(i * 3 + 2);
214 | }
215 | out.write((char *)&x, sizeof(x));
216 | out.write((char *)&y, sizeof(y));
217 | out.write((char *)&z, sizeof(z));
218 | out.write((char *)&r, sizeof(r));
219 | out.write((char *)&g, sizeof(g));
220 | out.write((char *)&b, sizeof(b));
221 | }
222 | if (pick_landmark && cnt != n_landmark) {
223 | bfm_out << "[ERROR] Pick too less landmarks.\n";
224 | bfm_out << "Number of picked points is " << cnt << ".\n";
225 | }
226 |
227 | unsigned char N_VER_PER_FACE = 3;
228 | for (int i = 0; i < n_face; i++) {
229 | out.write((char *)&N_VER_PER_FACE, sizeof(N_VER_PER_FACE));
230 | int x = tl(i * 3) - 1;
231 | int y = tl(i * 3 + 1) - 1;
232 | int z = tl(i * 3 + 2) - 1;
233 | out.write((char *)&y, sizeof(y));
234 | out.write((char *)&x, sizeof(x));
235 | out.write((char *)&z, sizeof(z));
236 | }
237 | out.close();
238 | }
--------------------------------------------------------------------------------
/bfm_visual_tool/bfm.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "data.h"
3 | #include "random.h"
4 |
5 | class bfm {
6 | public:
7 | bfm() {}
8 | bfm(const std::string &filename);
9 | void init(const std::string &filename);
10 | void data_check();
11 | void generate_random_face(double scale = 0.0);
12 | void generate_random_face(double shape_scale, double tex_scale, double expr_scale);
13 | void generate_average_face() { generate_random_face(0.0); }
14 | void generate_face();
15 | void ply_write(string fn = "rnd_face.ply", bool pick_landmarks = false);
16 | int get_n_id_pc() { return n_id_pc; }
17 | int get_n_expr_pc() { return n_expr_pc; }
18 | int get_n_face() { return n_face; }
19 | int get_n_vertice() { return n_vertice; }
20 | dlib::matrix &get_mutable_shape_coef() { return shape_coef; }
21 | dlib::matrix &get_mutable_tex_coef() { return tex_coef; }
22 | dlib::matrix &get_mutable_expr_coef() { return expr_coef; }
23 | const dlib::matrix &get_current_shape() { return current_shape; }
24 | const dlib::matrix &get_current_tex() { return current_tex; }
25 | const dlib::matrix &get_current_expr() { return current_expr; }
26 | const dlib::matrix &get_current_blendshape() { return current_blendshape; }
27 | const dlib::matrix &get_tl() { return tl; }
28 | private:
29 | bool read_parm_from_file(const std::string &filename);
30 | void init_parm();
31 | bool load_data();
32 | dlib::matrix coef2object(dlib::matrix &coef, dlib::matrix &mu,
33 | dlib::matrix &pc, dlib::matrix &ev);
34 |
35 | std::string bfm_h5_path;
36 | std::string landmark_idx_path;
37 |
38 | std::string shape_mu_h5_path;
39 | std::string shape_ev_h5_path;
40 | std::string shape_pc_h5_path;
41 |
42 | std::string tex_mu_h5_path;
43 | std::string tex_ev_h5_path;
44 | std::string tex_pc_h5_path;
45 |
46 | std::string expr_mu_h5_path;
47 | std::string expr_ev_h5_path;
48 | std::string expr_pc_h5_path;
49 |
50 | std::string tl_h5_path;
51 |
52 | int n_vertice;
53 | int n_face;
54 | int n_id_pc;
55 | int n_expr_pc;
56 | int n_landmark;
57 |
58 | double external_parm[6] = { 0.f }; /* yaw roll pitch tx ty tz */
59 | double intrinsic_parm[4] = { 0.f }; /* fx fy cx cy */
60 |
61 | dlib::matrix shape_coef;
62 | dlib::matrix shape_mu;
63 | dlib::matrix shape_ev;
64 | dlib::matrix shape_pc;
65 |
66 | dlib::matrix tex_coef;
67 | dlib::matrix tex_mu;
68 | dlib::matrix tex_ev;
69 | dlib::matrix tex_pc;
70 |
71 | dlib::matrix expr_coef;
72 | dlib::matrix expr_mu;
73 | dlib::matrix expr_ev;
74 | dlib::matrix expr_pc;
75 |
76 | dlib::matrix tl; /* triangle list */
77 |
78 | dlib::matrix current_shape;
79 | dlib::matrix current_tex;
80 | dlib::matrix current_expr;
81 | dlib::matrix current_blendshape;
82 |
83 | std::vector landmark_idx;
84 | };
--------------------------------------------------------------------------------
/bfm_visual_tool/bfm_tool.rc:
--------------------------------------------------------------------------------
1 | IDI_ICON1 ICON DISCARDABLE "./Resources/bfm_tool.ico"
--------------------------------------------------------------------------------
/bfm_visual_tool/bfm_visual_tool.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 |
14 | {B12702AD-ABFB-343A-A199-8E24837244A3}
15 | Qt4VSv1.0
16 | 10.0.17134.0
17 | bfm_visual_tool
18 |
19 |
20 |
21 | Application
22 | v141
23 |
24 |
25 | Application
26 | v141
27 |
28 |
29 |
30 | $(MSBuildProjectDirectory)\QtMsBuild
31 |
32 |
33 | $(SolutionDir)$(Platform)\$(Configuration)\
34 |
35 |
36 | $(SolutionDir)$(Platform)\$(Configuration)\
37 | D:\Software\hdf5\CMake-hdf5-1.10.5\CMake-hdf5-1.10.5\HDF5-1.10.5-win64\include;$(IncludePath);D:\Software\dlib\dlib-19.17\dlib-19.17;D:\Software\OpenCV3\opencv\build\include\opencv2;D:\Software\OpenCV3\opencv\build\include;D:\Software\OpenCV3\opencv\build\include\opencv
38 | D:\Software\hdf5\CMake-hdf5-1.10.5\CMake-hdf5-1.10.5\HDF5-1.10.5-win64\lib;$(LibraryPath);D:\Software\dlib\dlib-19.17\dlib-19.17;D:\Software\OpenCV3\opencv\build\x64\vc14\lib
39 | $(VC_ReferencesPath_x64);D:\Software\dlib\dlib-19.17\dlib-19.17;
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | true
59 | UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_OPENGL_LIB;QT_OPENGLEXTENSIONS_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions)
60 | .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtOpenGL;$(QTDIR)\include\QtOpenGLExtensions;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories)
61 | Disabled
62 | ProgramDatabase
63 | MultiThreadedDebugDLL
64 | true
65 |
66 |
67 | Windows
68 | $(OutDir)\$(ProjectName).exe
69 | $(QTDIR)\lib;%(AdditionalLibraryDirectories)
70 | true
71 | qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5OpenGLd.lib;opengl32.lib;glu32.lib;Qt5OpenGLExtensionsd.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)
72 |
73 |
74 | .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
75 | Moc'ing %(Identity)...
76 | .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName)\.;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtOpenGL;$(QTDIR)\include\QtOpenGLExtensions;$(QTDIR)\include\QtWidgets
77 | UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_OPENGL_LIB;QT_OPENGLEXTENSIONS_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions)
78 |
79 |
80 | Uic'ing %(Identity)...
81 | .\GeneratedFiles\ui_%(Filename).h
82 |
83 |
84 | Rcc'ing %(Identity)...
85 | .\GeneratedFiles\qrc_%(Filename).cpp
86 |
87 |
88 |
89 |
90 | true
91 | UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_OPENGL_LIB;QT_OPENGLEXTENSIONS_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions);H5_BUILT_AS_DYNAMIC_LIB;
92 | .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtOpenGL;$(QTDIR)\include\QtOpenGLExtensions;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories)
93 |
94 | MultiThreadedDLL
95 | true
96 | /bigobj %(AdditionalOptions)
97 |
98 |
99 | Windows
100 | $(OutDir)\$(ProjectName).exe
101 | $(QTDIR)\lib;%(AdditionalLibraryDirectories);D:\Software\dlib\build2\Debug
102 | false
103 | qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5OpenGL.lib;opengl32.lib;glu32.lib;Qt5OpenGLExtensions.lib;Qt5Widgets.lib;%(AdditionalDependencies);szip.lib;zlib.lib;hdf5.lib;hdf5_cpp.lib;dlib.lib;opencv_world320.lib;
104 |
105 |
106 | .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
107 | Moc'ing %(Identity)...
108 | .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName)\.;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtOpenGL;$(QTDIR)\include\QtOpenGLExtensions;$(QTDIR)\include\QtWidgets
109 | UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_OPENGL_LIB;QT_OPENGLEXTENSIONS_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions);H5_BUILT_AS_DYNAMIC_LIB;
110 |
111 |
112 | Uic'ing %(Identity)...
113 | .\GeneratedFiles\ui_%(Filename).h
114 |
115 |
116 | Rcc'ing %(Identity)...
117 | .\GeneratedFiles\qrc_%(Filename).cpp
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/bfm_visual_tool/bfm_visual_tool.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}
14 | qrc;*
15 | false
16 |
17 |
18 | {99349809-55BA-4b9d-BF79-8FDBB0286EB3}
19 | ui
20 |
21 |
22 | {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E}
23 | qrc;*
24 | false
25 |
26 |
27 | {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11}
28 | moc;h;cpp
29 | False
30 |
31 |
32 | {9b057d09-802b-46f7-a10f-459442a4343e}
33 |
34 |
35 | {3b2f48ab-e426-4a03-8770-59e185a22d09}
36 |
37 |
38 |
39 |
40 | Source Files
41 |
42 |
43 | Source Files
44 |
45 |
46 | Source Files
47 |
48 |
49 | Source Files\bfm_utils
50 |
51 |
52 | Source Files\bfm_utils
53 |
54 |
55 | Source Files
56 |
57 |
58 |
59 |
60 | Header Files
61 |
62 |
63 | Header Files
64 |
65 |
66 |
67 |
68 | Form Files
69 |
70 |
71 |
72 |
73 | Resource Files
74 |
75 |
76 |
77 |
78 | Header Files\bfm_utils
79 |
80 |
81 | Header Files\bfm_utils
82 |
83 |
84 | Header Files\bfm_utils
85 |
86 |
87 | Header Files\bfm_utils
88 |
89 |
90 | Header Files\bfm_utils
91 |
92 |
93 |
94 |
95 | Resource Files
96 |
97 |
98 |
99 |
100 | Resource Files
101 |
102 |
103 |
--------------------------------------------------------------------------------
/bfm_visual_tool/bfm_visual_tool.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | D:\Software\qt\qt\5.13.1\msvc2017_64
6 | PATH=$(QTDIR)\bin%3b$(PATH)
7 |
8 |
9 | D:\Software\qt\qt\5.13.1\msvc2017_64
10 | PATH=$(QTDIR)\bin%3b$(PATH)
11 |
12 |
--------------------------------------------------------------------------------
/bfm_visual_tool/constant.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #define USE_QT true
5 |
6 | #ifdef USE_QT
7 | #include
8 | #define bfm_out qDebug()
9 | #else
10 | #define bfm_out std::cout
11 | #endif
12 |
13 | /* camera type */
14 | typedef int camera_type;
15 | enum {
16 | PARALLEL = 0,
17 | PINHOLE = 1,
18 | };
19 |
20 | typedef int op_type;
21 | enum {
22 | COARSE = 0,
23 | REAL = 1,
24 | };
--------------------------------------------------------------------------------
/bfm_visual_tool/data.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include "vec.h"
6 | #include "constant.h"
7 | #include "H5Cpp.h"
8 |
9 | using namespace H5;
10 | using namespace std;
11 |
12 | /* Macro Function: load_hdf5_model
13 | * Usage: load_hdf5_model(model_type, dataset_path, data_type);
14 | * Parameters:
15 | * model_type: data name, e.g. shape_mu;
16 | * dataset_path: dataset path in .h5 file, e.g. "/shape/model/mean"
17 | * data_type: data type in dataset, e.g. PredType::NATIVE_FLOAT
18 | * ***********************************************************************
19 | * Load data from .h5 format file into corresponding data struction.
20 | */
21 |
22 | #define load_hdf5_model(model_type, dataset_path, data_type) { \
23 | DataSet model_type##_data = file.openDataSet(dataset_path); \
24 | model_type##_data.read(model_type##_raw, data_type); \
25 | model_type##_data.close(); \
26 | raw2matrix(model_type, model_type##_raw); \
27 | delete[] model_type##_raw; \
28 | }
29 |
30 |
31 | template
32 | void raw2matrix(dlib::matrix &m, T *raw) {
33 | bfm_out << "check: " << m.nr() << " " << m.nc() << "\n";
34 | for (int i = 0; i < m.nr(); i++)
35 | for (int j = 0; j < m.nc(); j++)
36 | m(i, j) = raw[i * m.nc() + j];
37 | }
38 |
--------------------------------------------------------------------------------
/bfm_visual_tool/inputs-2017.txt:
--------------------------------------------------------------------------------
1 | D:\database\bfm\2017\model2017-1_bfm_nomouth.h5
2 | 53149 105694 199 100
3 | 68 D:\database\bfm\3DMM_model\landmark.anl
4 | 1744.327628674942 1747.838275588676 800 600
5 | shape/model/mean shape/model/pcaVariance shape/model/pcaBasis
6 | color/model/mean color/model/pcaVariance color/model/pcaBasis
7 | expression/model/mean expression/model/pcaVariance expression/model/pcaBasis
8 | shape/representer/cells
--------------------------------------------------------------------------------
/bfm_visual_tool/inputs.txt:
--------------------------------------------------------------------------------
1 | D:\database\bfm\3DMM_model\BaselFaceModel_mod.h5
2 | 46990 93322 99 29
3 | 68 D:\database\bfm\3DMM_model\landmark_outer.anl
4 | 1744.327628674942 1747.838275588676 800 600
5 | shapeMU shapeEV shapePC
6 | texMU texEV texPC
7 | expMU expEV expPC
8 | faces
9 |
--------------------------------------------------------------------------------
/bfm_visual_tool/main.cpp:
--------------------------------------------------------------------------------
1 | #include "MainWindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainWindow w;
8 | w.show();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------
/bfm_visual_tool/random.cpp:
--------------------------------------------------------------------------------
1 | #include "random.h"
2 |
3 | dlib::matrix randn(int n, double scale) {
4 | dlib::matrix res(n, 1);
5 | std::default_random_engine e;
6 | e.seed(time(NULL));
7 | std::normal_distribution dis(0, scale);
8 | for (int i = 0; i < n; i++)
9 | res(i) = dis(e);
10 | return res;
11 | }
12 |
--------------------------------------------------------------------------------
/bfm_visual_tool/random.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 |
6 | /* Function: randn
7 | * Usage:
8 | * std::vector seq = randn(n);
9 | * std::vector seq = randn(n, scale);
10 | * Parameters:
11 | * n - The number of random element to be generated.
12 | * -------------------------------------------------------------
13 | * Generate a sequence of random numbers into a vector sequence.
14 | * Its distribution is normal distribution whose sigma = 0 ,and
15 | * miu = 1.
16 | */
17 |
18 | dlib::matrix randn(int n, double scale);
--------------------------------------------------------------------------------
/bfm_visual_tool/vec.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | /* Definition of 3d coordinate, because dlib only support dlib::point, which is 2d */
6 | typedef dlib::vector point3f;
7 | typedef dlib::vector point3d;
8 | template using point3x = dlib::vector;
9 | typedef dlib::point point2d;
--------------------------------------------------------------------------------