├── .gitmodules
├── 1_new.obj
├── 2_new.obj
├── CMakeLists.txt
├── LICENSE
├── README.md
├── get_dr.cpp
├── test.py
├── util_3drotation_log_exp.cpp
└── util_3drotation_log_exp.h
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "pybind11"]
2 | path = pybind11
3 | url = https://github.com/pybind/pybind11.git
4 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8.12)
2 | project(my_project)
3 |
4 | # force a specific python version
5 | # set(PYTHON_LIBRARIES "/usr/lib/x86_64-linux-gnu/libpython2.7.a")
6 | # set(PYTHON_INCLUDE_DIR "/usr/include/python2.7")
7 |
8 | find_package(PythonInterp REQUIRED)
9 | find_package(PythonLibs REQUIRED)
10 |
11 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -w -shared -std=c++11")
12 |
13 | add_subdirectory(pybind11)
14 |
15 | pybind11_add_module(get_dr get_dr.cpp util_3drotation_log_exp.h util_3drotation_log_exp.cpp)
16 |
17 |
18 | INCLUDE_DIRECTORIES("/usr/include/eigen3")
19 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR})
20 |
21 | link_directories("/usr/local/lib")
22 |
23 | target_link_libraries(get_dr PRIVATE -lOpenMeshCore -lOpenMeshTools)
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2019, Wooqy
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # get_dr_py_API
2 | This package is available for using pybind11 to create get_dr python API.
3 |
4 | Deformation Representation Feature (DR Feature) is a kind of fundamental and stable tool in geometry learning area. For more background knowledges and properties of DR feature, we suggest these papers in **Citation** section for further reading.
5 |
6 | # Dependencies
7 | This package depends on OpenMesh and Eigen libraries. To run the dr computation code, please make sure you have Eigen and OpenMesh precompiled on your computer and modificate the include path in CMakeList.txt file.
8 |
9 | # Usage
10 | We recommend to use cmake to compile this package and a python API will be automatically created to compute DR features.
11 | ```
12 | git clone --recursive https://github.com/QianyiWu/get_dr_py.git
13 | cd get_dr_py
14 | ```
15 |
16 | After obtaining this repository, run the following code in the repository path:
17 | ```
18 | mkdir build
19 | cd build
20 | cmake ..
21 | make -j4
22 | ```
23 | You will then get a .so file.
24 | The test.py with *1_new.obj* and *2_new.obj* could be used for testing.
25 |
26 | # Environment Tests
27 | Currently we have fully tested this package on Ubuntu 16.04 LTS environment. Windows and MacOS are not ensured working.
28 |
29 | # Citation
30 | Please cite the following papers if it helps your research:
31 |
32 | Disentangled Representation Learning for 3D Face Shape
33 |
34 | @inproceedings{Jiang2019Disentangled
35 | title={Disentangled Representation Learning for 3D Face Shape},
36 | author={Jiang, Zi-Hang and Wu, Qianyi and Chen, Keyu and Zhang, Juyong}
37 | booktitle={IEEE Conference on Computer Vision and Pattern Recognition (CVPR)},
38 | year={2019},
39 | }
40 |
41 | Sparse Data Driven Mesh Deformation
42 |
43 | @article{Gao2017SparseDD,
44 | title={Sparse Data Driven Mesh Deformation},
45 | author={Lin Gao and Yu-Kun Lai and Jie Yang and Ling-Xiao Zhang and Leif Kobbelt and Shihong Xia},
46 | journal={CoRR},
47 | year={2017},
48 | volume={abs/1709.01250}
49 | }
50 |
51 | Alive Caricature from 2D to 3D
52 |
53 | @inproceedings{wu2018alive,
54 | title={Alive Caricature from 2D to 3D},
55 | author={Wu, Qianyi and Zhang, Juyong and Lai, Yu-Kun and Zheng, Jianmin and Cai, Jianfei},
56 | booktitle={IEEE Conference on Computer Vision and Pattern Recognition (CVPR)},
57 | year={2018},
58 | }
59 |
--------------------------------------------------------------------------------
/get_dr.cpp:
--------------------------------------------------------------------------------
1 | #include "util_3drotation_log_exp.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include ;
11 |
12 | namespace py=pybind11;
13 |
14 | struct TriTraits : public OpenMesh::DefaultTraits
15 | {
16 | /// Use double precision points
17 | typedef OpenMesh::Vec3d Point;
18 | /// Use double precision Normals
19 | typedef OpenMesh::Vec3d Normal;
20 | /// Use double precision TexCood2D
21 | typedef OpenMesh::Vec2d TexCoord2D;
22 |
23 | /// Use RGBA Color
24 | typedef OpenMesh::Vec4f Color;
25 |
26 | /// Status
27 | VertexAttributes(OpenMesh::Attributes::Status);
28 | FaceAttributes(OpenMesh::Attributes::Status);
29 | EdgeAttributes(OpenMesh::Attributes::Status);
30 |
31 | // VertexAttributes(
32 | // OpenMesh::Attributes::
33 | // )
34 | };
35 |
36 | /// Simple Name for Mesh
37 | typedef OpenMesh::TriMesh_ArrayKernelT TriMesh;
38 |
39 | class DR_feature{
40 | public:
41 | DR_feature();
42 | void read_ref_mesh(std::string ref_mesh_name);
43 | void read_defor_mesh(std::string defor_mesh_name);
44 | std::vector get_feature(std::string ref_mesh_name, std::string defor_mesh_name);
45 |
46 |
47 | private:
48 | TriMesh ref_mesh_;
49 | TriMesh defor_mesh_;
50 |
51 | OpenMesh::EPropHandleT LB_weights;
52 | OpenMesh::VPropHandleT T_matrixs;
53 | private:
54 | void compute_ref_LB_weight();
55 | void compute_Ti(TriMesh::VertexHandle v_it,TriMesh::VertexHandle v_to_it);
56 | };
57 |
58 | DR_feature::DR_feature(){
59 | ref_mesh_.add_property(LB_weights);
60 | defor_mesh_.add_property(T_matrixs);
61 | }
62 |
63 | void DR_feature::read_ref_mesh(std::string ref_mesh_name){
64 | if(!OpenMesh::IO::read_mesh(ref_mesh_, ref_mesh_name)){
65 | std::cout<<"read_ref_mesh_ : read file wrong!!!"<tolerance)
243 | T = L*RI.inverse();
244 | else
245 | {
246 | Eigen::JacobiSVD svd(RI, Eigen::ComputeThinU | Eigen::ComputeThinV);
247 | Eigen::Matrix3d U,V;
248 | U=svd.matrixU();
249 | V=svd.matrixV();
250 | Eigen::Matrix3d S_inv(svd.singularValues().asDiagonal());
251 | for(int i=0;i<3;i++)
252 | {
253 | if(fabs(S_inv(i,i))>tolerance)
254 | S_inv(i,i)=1.0/S_inv(i,i);
255 | else
256 | S_inv(i,i)=0.0;
257 | }
258 | T = L*V*S_inv*U.transpose();
259 | }
260 | defor_mesh_.property(T_matrixs,v_it) = T;
261 | }
262 |
263 |
264 | std::vector DR_feature::get_feature(std::string ref_mesh_name, std::string defor_mesh_name){
265 | read_ref_mesh(ref_mesh_name);
266 | read_defor_mesh(defor_mesh_name);
267 |
268 | std::vector dr_feature;
269 |
270 | TriMesh::VertexIter v_it;
271 | for(v_it=defor_mesh_.vertices_begin(); v_it!=defor_mesh_.vertices_end(); v_it++)
272 | {
273 | Eigen::Matrix3d T = defor_mesh_.property(T_matrixs,*v_it);
274 | Eigen::JacobiSVD svd(T, Eigen::ComputeThinU | Eigen::ComputeThinV);
275 | Eigen::Matrix3d U,V;
276 | U=svd.matrixU();
277 | V=svd.matrixV();
278 | Eigen::Matrix3d S(svd.singularValues().asDiagonal());
279 | Eigen::Matrix3d Temp=Eigen::Matrix3d::Identity();
280 | Temp(2,2) = (U*V.transpose()).determinant();
281 | Eigen::Matrix3d R=U*Temp*V.transpose();
282 | Eigen::Matrix3d Scale = V*Temp*S*V.transpose();
283 | Eigen::Matrix3d logR = rotation_log_exp::log(R);
284 |
285 | dr_feature.push_back(Scale(0, 0));
286 | dr_feature.push_back(Scale(0, 1));
287 | dr_feature.push_back(Scale(0, 2));
288 | dr_feature.push_back(Scale(1, 1));
289 | dr_feature.push_back(Scale(1, 2));
290 | dr_feature.push_back(Scale(2, 2));
291 | dr_feature.push_back(logR(0, 1));
292 | dr_feature.push_back(logR(0, 2));
293 | dr_feature.push_back(logR(1, 2));
294 | }
295 | return dr_feature;
296 | }
297 |
298 | py::array_t get_dr(std::string ref_mesh_name, std::string defor_mesh_name){
299 | DR_feature feature;
300 | std::vector temp = feature.get_feature(ref_mesh_name, defor_mesh_name);
301 |
302 | auto result = py::array_t(temp.size());
303 | auto result_buffer = result.request();
304 | double *result_ptr = (double *)result_buffer.ptr;
305 |
306 | std::memcpy(result_ptr, temp.data(), temp.size()*sizeof(double));
307 |
308 | return result;
309 |
310 | }
311 |
312 | PYBIND11_MODULE(get_dr, m){
313 | m.doc() = "get dr";
314 | m.def("get_dr", &get_dr, "get_dr");
315 | }
--------------------------------------------------------------------------------
/test.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.append('build')
3 | from get_dr import *
4 | import numpy as np
5 | import time
6 | print(get_dr('1_new.obj', '2_new.obj'))
7 |
--------------------------------------------------------------------------------
/util_3drotation_log_exp.cpp:
--------------------------------------------------------------------------------
1 | #include "util_3drotation_log_exp.h"
2 | #include
3 |
4 | Eigen::Matrix3d rotation_log_exp::exp(double angle, const Eigen::Vector3d &axis)
5 | {
6 | if(fabs(axis.norm()-1.0)>log_exp_tolerance)
7 | {
8 | std::cout<<"rotation_log_exp::exp1::input axis isn't an unit direction!!!"<log_exp_tolerance)
24 | {
25 | std::cout<<"rotation_log_exp::exp2::input matrix isn't skew-matrix!!!"<log_exp_tolerance)
36 | {
37 | std::cout<<"rotation_log_exp::exp3::input matrix isn't skew-matrix!!!"<log_exp_tolerance)
74 | {
75 | std::cout<<"rotation_log_exp::log::rotation_matrix isn't an orthogonal matrix!!!"<1.0)
80 | {
81 | if(fabs(csin-1.0)>log_exp_tolerance&&fabs(csin+1.0)>log_exp_tolerance)
82 | {
83 | std::cout<<"rotation_log_exp::log::csin "<0.0) k2 = sqrt(B(1,1));
103 | else k2 = -sqrt(B(1,1));
104 | if(k1*B(0,2)>0.0) k3 = sqrt(B(2,2));
105 | else k3 = -sqrt(B(2,2));
106 | axis(0)=k1;axis(1)=k2;axis(2)=k3;
107 | return ;
108 | }
109 |
110 | //tangle has 2 possible, 0~pi or pi~2pi
111 | Eigen::Vector3d taxis;
112 | taxis(0)=rotation_matrix(2,1)-rotation_matrix(1,2);
113 | taxis(1)=rotation_matrix(0,2)-rotation_matrix(2,0);
114 | taxis(2)=rotation_matrix(1,0)-rotation_matrix(0,1);
115 | Eigen::Vector3d t_axis=taxis/(2.0*sin(tangle));
116 | double sinv = sin(tangle);
117 | double r01 = (1.0-csin)*t_axis(0)*t_axis(1)-t_axis(2)*sinv;
118 | double r02 = (1.0-csin)*t_axis(0)*t_axis(2)+t_axis(1)*sinv;
119 | double r10 = (1.0-csin)*t_axis(0)*t_axis(1)+t_axis(2)*sinv;
120 | double r12 = (1.0-csin)*t_axis(1)*t_axis(2)-t_axis(0)*sinv;
121 | double r20 = (1.0-csin)*t_axis(0)*t_axis(2)-t_axis(1)*sinv;
122 | double r21 = (1.0-csin)*t_axis(1)*t_axis(2)+t_axis(0)*sinv;
123 | double check = (rotation_matrix(0,1)-r01)*(rotation_matrix(0,1)-r01)+(rotation_matrix(0,2)-r02)*(rotation_matrix(0,2)-r02)
124 | +(rotation_matrix(1,0)-r10)*(rotation_matrix(1,0)-r10)+(rotation_matrix(1,2)-r12)*(rotation_matrix(1,2)-r12)
125 | +(rotation_matrix(2,0)-r20)*(rotation_matrix(2,0)-r20)+(rotation_matrix(2,1)-r21)*(rotation_matrix(2,1)-r21);
126 |
127 | if(checklog_exp_tolerance)
149 | std::cout<<"rotation_log_exp::log::computation is wrong!!!"<log_exp_tolerance)
191 | {
192 | std::cout<<"rotation_log_exp::exp1::input axis isn't an unit direction!!!"<
4 |
5 |
6 | //rotation matrix log and exp operation, reference Axis–angle representation on wiki
7 | namespace rotation_log_exp
8 | {
9 | static double log_exp_tolerance = 1.0e-6;
10 | Eigen::Matrix3d exp(const Eigen::Vector3d &angle_axis);
11 | Eigen::Matrix3d exp(double angle,const Eigen::Vector3d &axis);
12 | Eigen::Matrix3d exp(double angle,const Eigen::Matrix3d &cross_axis);
13 | Eigen::Matrix3d exp(const Eigen::Matrix3d &angle_cross_axis);
14 |
15 | void log(const Eigen::Matrix3d &rotation_matrix,double &angle,Eigen::Vector3d &axis);
16 | void log(const Eigen::Matrix3d &rotation_matrix,double &angle,Eigen::Matrix3d &cross_axis);
17 | Eigen::Matrix3d log(const Eigen::Matrix3d &rotation_matrix);
18 |
19 | Eigen::Matrix3d rotation_so3(const Eigen::Vector3d &angle_axis);
20 | Eigen::Matrix3d rotation_so3(double angle,const Eigen::Vector3d &axis);
21 |
22 | void so3_to_angle_axis(const Eigen::Matrix3d &r, double &angle, Eigen::Vector3d &axis);
23 | }
24 |
25 |
26 | #endif // ROTATION_H
27 |
--------------------------------------------------------------------------------