
3D face: fast, accurate and stable reconstruction - cleardusk
https://github.com/cleardusk/3DDFA_V2
======
yboris
I love that the _Colab_ notebook runs flawlessly!

I humbly recommend you add code so people can try out with online images:

    
    
      from skimage import io
    
      def get_image_from_url(url):
        # download the image using scikit-image
        print("downloading", url)
        image = io.imread(url)
        return image

~~~
cleardusk
Thanks for your advice : )

------
hnarn
This looks really impressive, and I don't want to take anything away from the
quality of the code itself here, but I feel like I have to point out that this
repo is a school book example of how commit messages should _not_ look:

\- "update"
[https://github.com/cleardusk/3DDFA_V2/commit/a339c36d795b4d6...](https://github.com/cleardusk/3DDFA_V2/commit/a339c36d795b4d623f9d69cea2508a1977f3d694)

\- "some updates"
[https://github.com/cleardusk/3DDFA_V2/commit/a8cab53dbaa87d1...](https://github.com/cleardusk/3DDFA_V2/commit/a8cab53dbaa87d16dd90c265458a231c2718b474)
(license change mixed with code)

This is an easy pattern to fall into when you're the only one in the project,
I've been there myself, because you feel like "it doesn't matter, this isn't
quite done yet anyway, and noone else will read it".

Well, here's the point:

\- "Someone else" may very well be yourself a few months from now. Don't avoid
good git practice, you're shooting yourself in the foot.

\- Even if noone will read it now, someone may read it way down the line, when
that one line you changed caused a really annoying bug. Imagine the feeling
when the commit has no information on why the change was made. Commit messages
are mandatory for a reason.

\- If commit messages are not atomic and mix different files that aren't
logically related, understanding what was done will be extremely hard, even
for yourself looking back.

There are many guides available online on how to write good commit messages, I
won't point out a single one of them as I don't feel one is authoritative over
all others.

I'd also like to point out that this is something you _need_ to know if you're
ever going to collaborate on software projects, so learning it now is as good
as a time as any.

~~~
cleardusk
Thanks for your advice. I have no experience on a cooperative project before,
so my committed messages are kind of meaningless. I think you are right. I
will read the committing guidance and take care of them later. Thanks for your
critical voice again.

~~~
choppaface
Having flexibility for “pointless” commit messages is really important for
research-y projects. Sadly, the practice often clashes with readers who have
never really done research before.

A nice compromise is to use Github PRs plus squash-merge commits (search for
“Github squash merge button”). For example, you might start a project, commit
a bunch of “garbage” commit messages, and then decide the project is ready for
initial release. Then take your branch, create a PR, and squash-merge it to
your master branch _with a nice commit message_.

Need to update your paper on arxiv? Create a branch, commit willy-nilly, the
squash-merge the result with a nice message (that perhaps references the
updated arxiv version).

If for some reason your project grows like Caffe did years ago, then it can be
time for smaller PRs and more organized commit messages.

~~~
cleardusk
Thanks for your detailed reply and explaination. I learned from it.

------
rhacker
The cost of motion capture for video games, movies and deep fakes just dropped
significantly.

------
ur-whale
Very, very nice, congratulations.

And it pretty much works out of the box, something rather unusual for
researchy code.

What would make this absolutely great is there was a way to output a wavefront
OBJ file for the dense 3D geometry.

~~~
ur-whale
Never mind, it was easy: just add the following code at line 45 of demo.py:

    
    
        # Output .ply geometry for each face detected
        ocnt = 0
        for face in ver_lst:
            with open('face_%04d.ply' % ocnt, 'w') as f:
                x = face[0]
                y = face[1]
                z = face[2]
                n = x.size
                print('ply', file=f)
                print('format ascii 1.0', file=f)
                print('element vertex %d' % n, file=f)
                print('property float x', file=f)
                print('property float y', file=f)
                print('property float z', file=f)
                print('element face 0', file=f)
                print('property list uchar int vertex_indices', file=f)
                print('end_header', file=f)
                for i in range(0, n):
                    print("%12.8f %12.8f %12.8f" % (x[i], y[i], z[i]), file=f)
                ocnt += 1

~~~
cleardusk
Thanks, I will consider adding it later :)

------
cleardusk
Welcome to give it a try :)

~~~
abetusk
I had some problems getting it to run but after some handholding I managed to
get all the demos to run. Amazing stuff!

I'll try to open an issue with all the problems I encountered.

I would also appreciate a demo with data output as well (actual 2d/3d points)
along with a short description of what the format is.

Can this be used real-time?

~~~
cleardusk
Thanks for your interest and try. The theory computation complexity is
described in the paper, it is rather small. However, whether achieving real-
time really depends on your hardware, your need and the code optimization.

------
ionwake
Sorry to ask, but in the images of the example of it working - what face is it
using over the one of Emma Watson? Is it just a random 3d face?

~~~
cleardusk
Not a random face. But it may not look very similar.

------
rkagerer
Anyone have a copy of the demo GIF I can look at? GitHub pages is having
issues right now ("Error 503 Backend is unhealthy")

~~~
cleardusk
The access is OK.

------
fxtentacle
Wow, that's very impressive performance. Thanks for sharing :)

~~~
cleardusk
:)

