Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
py-3d-face-reconstruction
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Richard Torenvliet
py-3d-face-reconstruction
Commits
88963c53
Commit
88963c53
authored
May 19, 2016
by
Richard Torenvliet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make a way of showing the pca model getting the texture of the given image
parent
265501fa
Changes
12
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
329 additions
and
8376 deletions
+329
-8376
.gitignore
.gitignore
+4
-0
actions.mk
actions.mk
+9
-7
makefile
makefile
+7
-1
src/aam.py
src/aam.py
+31
-50
src/imm_points.py
src/imm_points.py
+12
-12
src/main.py
src/main.py
+57
-10
src/utils/build/temp.macosx-10.11-x86_64-2.7/generate_head_texture.o
...uild/temp.macosx-10.11-x86_64-2.7/generate_head_texture.o
+0
-0
src/utils/generate_head_texture.c
src/utils/generate_head_texture.c
+0
-8258
src/utils/generate_head_texture.pyx
src/utils/generate_head_texture.pyx
+67
-27
src/utils/generate_head_texture.so
src/utils/generate_head_texture.so
+0
-0
src/utils/triangles.py
src/utils/triangles.py
+85
-0
src/view/reconstruct.py
src/view/reconstruct.py
+57
-11
No files found.
.gitignore
View file @
88963c53
data/*
src/.cache/*
src/utils/*.c
src/utils/*.o
src/utils/*.so
src/utils/build/
actions.mk
View file @
88963c53
...
...
@@ -14,35 +14,37 @@ data/imm_face_db.tar.gz:
data/pca_shape_model.npy
:
python src/main.py
\
--save_pca_shape
\
--
asf
`
./scripts/imm_train_set.sh
`
\
--
files
`
./scripts/imm_train_set.sh
`
\
--model_shape_file
data/pca_shape_model
data/pca_texture_model.npy
:
python src/main.py
\
--save_pca_texture
\
--
asf
`
./scripts/imm_train_set.sh
`
\
--
files
`
./scripts/imm_train_set.sh
`
\
--model_texture_file
data/pca_texture_model
\
--model_shape_file
data/pca_shape_model.npy
show_pca
:
python src/main.py
\
--show_pca
\
--asf
data/imm_face_db/
*
.asf
\
--model_shape_file
data/pca_model.npy
--model_texture_file
data/pca_texture_model.npy
\
--model_shape_file
data/pca_shape_model.npy
test_model
:
python src/main.py
\
--reconstruct
\
--asf
`
./scripts/imm_test_set.sh
`
\
--files
`
./scripts/imm_test_set.sh
`
\
--model_texture_file
data/pca_texture_model
\
--model_shape_file
data/pca_shape_model.npy
\
--n_components
6
show_reconstruction
:
python src/main.py
\
--reconstruct
\
--asf
data/imm_face_db/
*
.asf
\
--model_shape_file
data/pca_shape_model.npy
\
--files
data/imm_face_db/
*
.asf
\
--model_texture_file
data/pca_texture_model.npy
\
--model_shape_file
data/pca_shape_model.npy
\
--n_components
6
test
:
...
...
makefile
View file @
88963c53
...
...
@@ -5,7 +5,7 @@ SITE_PACKAGES := $(VIRTUALENV)/lib/$(PYTHON)/site-packages
OPENCV
:=
$(SITE_PACKAGES)
/cv.py
$(SITE_PACKAGES)
/cv2.so
TARGETS
:=
$(VIRTUALENV)
data build
TARGETS
:=
$(VIRTUALENV)
data build
utils
all
:
$(TARGETS)
include
actions.mk
...
...
@@ -13,6 +13,12 @@ include build.mk
data
:
data/imm_face_db
utils
:
generate_head_texture.so
generate_head_texture.so
:
src/utils/generate_head_texture.pyx
(
cd
src/utils
;
python setup.py build_ext
--inplace
)
build
:
$(OPENCV)
@
(
source
$(VIRTUALENV)
/bin/activate
;
\
pip
install
-r
requirements.txt
;
\
...
...
src/aam.py
View file @
88963c53
import
logging
from
matplotlib.tri
import
Triangulation
import
numpy
as
np
from
matplotlib.tri
import
Triangulation
import
cv2
import
pca
# local imports
import
pca
from
utils.generate_head_texture
import
fill_triangle
,
get_colors_triangle
import
utils.triangles
as
tu
logging
.
basicConfig
(
level
=
logging
.
INFO
,
format
=
'%(asctime)s %(levelname)s %(name)s: %(message)s'
)
...
...
@@ -51,7 +52,7 @@ def get_triangles(x_vector, y_vector):
return
Triangulation
(
x_vector
,
y_vector
).
triangles
def
build_feature_vectors
(
files
,
get_points
,
flattened
=
False
):
def
build_
shape_
feature_vectors
(
files
,
get_points
,
flattened
=
False
):
"""
Gets the aam points from the files and appends them seperately to one
array.
...
...
@@ -70,47 +71,14 @@ def build_feature_vectors(files, get_points, flattened=False):
return
points
def
cartesian2barycentric
(
r1
,
r2
,
r3
,
r
):
x
,
y
=
r
x1
,
y1
=
r1
x2
,
y2
=
r2
x3
,
y3
=
r3
a
=
np
.
array
([[
x1
,
x2
,
x3
],
[
y1
,
y2
,
y3
],
[
1
,
1
,
1
]])
b
=
np
.
array
([
x
,
y
,
1
])
return
np
.
linalg
.
solve
(
a
,
b
)
def
barycentric2cartesian
(
r1
,
r2
,
r3
,
L
):
x1
,
y1
=
r1
x2
,
y2
=
r2
x3
,
y3
=
r3
a
=
np
.
array
([[
x1
,
x2
,
x3
],
[
y1
,
y2
,
y3
],
[
1
,
1
,
1
]])
b
=
np
.
array
(
L
)
return
np
.
asarray
(
np
.
dot
(
a
,
b
),
dtype
=
np
.
uint32
)
def
sample_from_triangles
(
b
,
points2d_b
,
triangles
,
n_samples
=
20
):
def
sample_from_triangles
(
image
,
points2d
,
triangles
,
n_samples
=
20
):
all_triangles
=
[]
h
,
w
,
c
=
b
.
shape
h
,
w
,
c
=
image
.
shape
for
tri
in
triangles
:
p1_b
=
points2d_b
[
tri
[
0
]]
p2_b
=
points2d_b
[
tri
[
1
]]
p3_b
=
points2d_b
[
tri
[
2
]]
cv2
.
line
(
b
,
tuple
(
p1_b
),
tuple
(
p2_b
),
(
0
,
255
,
0
),
1
)
cv2
.
line
(
b
,
tuple
(
p2_b
),
tuple
(
p3_b
),
(
0
,
255
,
0
),
1
)
cv2
.
line
(
b
,
tuple
(
p3_b
),
tuple
(
p1_b
),
(
0
,
255
,
0
),
1
)
p1
=
points2d
[
tri
[
0
]]
p2
=
points2d
[
tri
[
1
]]
p3
=
points2d
[
tri
[
2
]]
bary_centric_range
=
np
.
linspace
(
0
,
1
,
num
=
n_samples
)
pixels
=
np
.
full
((
n_samples
*
n_samples
,
3
),
fill_value
=-
1
,
dtype
=
np
.
int
)
...
...
@@ -126,8 +94,8 @@ def sample_from_triangles(b, points2d_b, triangles, n_samples=20):
L
[
2
]
=
1
-
s
-
t
# cartesian x, y coordinates inside the triangle
cart_x
,
cart_y
,
_
=
barycentric2cartesian
(
p1_b
,
p2_b
,
p3_b
,
L
)
pixels
[
s_i
*
n_samples
+
t_i
,
:]
=
b
[
cart_y
,
cart_x
,
:]
cart_x
,
cart_y
,
_
=
tu
.
barycentric2cartesian
(
p1
,
p2
,
p3
,
L
)
pixels
[
s_i
*
n_samples
+
t_i
,
:]
=
image
[
cart_y
,
cart_x
,
:]
# cv2.circle(b, tuple([cart_x, cart_y]), 1, color=(0, 255, 100))
...
...
@@ -136,17 +104,27 @@ def sample_from_triangles(b, points2d_b, triangles, n_samples=20):
return
np
.
asarray
(
all_triangles
,
dtype
=
np
.
uint8
)
def
build_texture_feature_vector
(
files
,
get_image_with_landmarks
,
triangles
):
def
build_texture_feature_vectors
(
files
,
get_image_with_landmarks
,
triangles
,
flattened
=
True
):
mean_texture
=
[]
"""
Args:
files (list): list files
flattened (bool): Flatten the inner feature vectors, see
flatten_feature_vectors.
Returns:
list: list of feature vectors
"""
for
i
,
f
in
enumerate
(
files
[:
1
0
]):
for
i
,
f
in
enumerate
(
files
[:
1
]):
image
,
landmarks
=
get_image_with_landmarks
(
f
)
h
,
w
,
c
=
image
.
shape
landmarks
[:,
0
]
=
landmarks
[:,
0
]
*
w
landmarks
[:,
1
]
=
landmarks
[:,
1
]
*
h
triangles_colors
=
sample_from_triangles
(
image
,
landmarks
,
triangles
image
,
landmarks
,
triangles
,
n_samples
=
80
)
mean_texture
.
append
(
triangles_colors
)
...
...
@@ -158,7 +136,12 @@ def build_texture_feature_vector(files, get_image_with_landmarks, triangles):
# if k == 27:
# break
return
np
.
asarray
(
mean_texture
)
mean_texture
=
np
.
asarray
(
mean_texture
)
if
flattened
:
mean_texture
=
pca
.
flatten_feature_vectors
(
mean_texture
)
return
mean_texture
def
get_pixel_values
(
image
,
points
):
...
...
@@ -172,7 +155,6 @@ def get_pixel_values(image, points):
hull
=
cv2
.
convexHull
(
points
,
returnPoints
=
True
)
rect
=
cv2
.
boundingRect
(
hull
)
pixels
=
[]
x
,
y
,
w
,
h
=
rect
# pixels = np.zeros((h, w, c), dtype=np.uint8)
...
...
@@ -185,7 +167,6 @@ def get_pixel_values(image, points):
image
[
y_loc_g
][
x_loc_g
][
0
]
=
0
image
[
y_loc_g
][
x_loc_g
][
1
]
=
0
image
[
y_loc_g
][
x_loc_g
][
2
]
=
0
pixels
.
extend
(
image
[
y_loc_g
][
x_loc_g
])
# return np.asarray(pixels, dtype=np.uint8), hull
return
image
,
hull
src/imm_points.py
View file @
88963c53
...
...
@@ -38,9 +38,9 @@ class IMMPoints():
self
.
points
=
np
.
asarray
(
self
.
points
,
dtype
=
'f'
)
def
draw_triangles
(
self
,
im
g
,
points
,
multiply
=
True
):
def
draw_triangles
(
self
,
im
age
,
points
,
multiply
=
True
):
if
multiply
:
h
,
w
,
c
=
im
g
.
shape
h
,
w
,
c
=
im
age
.
shape
points
[:,
0
]
=
points
[:,
0
]
*
w
points
[:,
1
]
=
points
[:,
1
]
*
h
...
...
@@ -50,30 +50,30 @@ class IMMPoints():
for
t
,
tri
in
enumerate
(
triangles
.
triangles
):
p1
,
p2
,
p3
=
points
[
tri
]
cv2
.
line
(
im
g
,
tuple
(
p1
),
tuple
(
p2
),
(
255
,
0
,
100
),
1
)
cv2
.
line
(
im
g
,
tuple
(
p2
),
tuple
(
p3
),
(
255
,
0
,
100
),
1
)
cv2
.
line
(
im
g
,
tuple
(
p3
),
tuple
(
p1
),
(
255
,
0
,
100
),
1
)
cv2
.
line
(
im
age
,
tuple
(
p1
),
tuple
(
p2
),
(
255
,
0
,
100
),
1
)
cv2
.
line
(
im
age
,
tuple
(
p2
),
tuple
(
p3
),
(
255
,
0
,
100
),
1
)
cv2
.
line
(
im
age
,
tuple
(
p3
),
tuple
(
p1
),
(
255
,
0
,
100
),
1
)
for
i
,
p
in
enumerate
(
points
):
point_index
=
int
(
point_indices
[
i
])
cv2
.
putText
(
im
g
,
str
(
point_index
),
tuple
((
p
[
0
],
p
[
1
])),
cv2
.
putText
(
im
age
,
str
(
point_index
),
tuple
((
p
[
0
],
p
[
1
])),
cv2
.
FONT_HERSHEY_SIMPLEX
,
.
5
,
(
100
,
0
,
255
))
cv2
.
circle
(
im
g
,
tuple
(
p
),
3
,
color
=
(
0
,
255
,
100
))
cv2
.
circle
(
im
age
,
tuple
(
p
),
3
,
color
=
(
0
,
255
,
100
))
def
show_on_im
g
(
self
,
img
,
window_name
=
'image'
,
multiply
=
True
):
self
.
draw_triangles
(
im
g
,
self
.
points
,
multiply
=
multiply
)
def
show_on_im
age
(
self
,
image
,
window_name
=
'image'
,
multiply
=
True
):
self
.
draw_triangles
(
im
age
,
self
.
points
,
multiply
=
multiply
)
def
show
(
self
,
window_name
=
'image'
):
"""show the image and datapoints on the image"""
assert
(
len
(
self
.
points
)
>
0
)
assert
(
len
(
self
.
filename
)
>
0
)
im
g
=
self
.
get_image
()
im
age
=
self
.
get_image
()
self
.
draw_triangles
(
im
g
,
self
.
points
)
self
.
draw_triangles
(
im
age
,
self
.
points
)
def
get_imm_
landmark
s
(
files
):
def
get_imm_
point
s
(
files
):
points
=
[]
for
f
in
files
:
...
...
src/main.py
View file @
88963c53
# python std
import
argparse
import
logging
import
sys
# installed packages
import
cv2
import
numpy
as
np
# local imports
import
pca
import
aam
...
...
@@ -36,9 +41,8 @@ def add_parser_options():
help
=
'Show and manipulate the saved PCA model'
)
# asf model_files
pca_group
.
add_argument
(
'--
asf'
,
nargs
=
'+'
,
help
=
'asf
files to process'
'--
files'
,
nargs
=
'+'
,
help
=
'
files to process'
)
pca_group
.
add_argument
(
...
...
@@ -76,14 +80,14 @@ def save_pca_model_texture(args):
mean_values = Vtm[1][0]
"""
assert
args
.
asf
,
'--asf
files should be given'
assert
args
.
files
,
'--
files should be given'
assert
args
.
model_shape_file
,
'--model_texture_file needs to be provided to save the pca model'
assert
args
.
model_texture_file
,
'--model_texture_file needs to be provided to save the pca model'
Vt
,
mean_values
,
triangles
=
pca
.
load
(
args
.
model_shape_file
)
textures
=
aam
.
build_texture_feature_vector
(
args
.
asf
,
imm
.
get_imm_image_with_landmarks
,
triangles
textures
=
aam
.
build_texture_feature_vector
s
(
args
.
files
,
imm
.
get_imm_image_with_landmarks
,
triangles
,
flattened
=
True
)
mean_texture
=
aam
.
get_mean
(
textures
)
...
...
@@ -110,11 +114,11 @@ def save_pca_model_shape(args):
mean_values = Vtm[1][0]
"""
assert
args
.
asf
,
'--asf
files should be given'
assert
args
.
files
,
'--
files should be given'
assert
args
.
model_shape_file
,
'--model_shape_file needs to be provided to save the pca model'
points
=
aam
.
build_
feature_vectors
(
args
.
asf
,
imm
.
get_imm_landmark
s
,
flattened
=
True
)
points
=
aam
.
build_
shape_feature_vectors
(
args
.
files
,
imm
.
get_imm_point
s
,
flattened
=
True
)
mean_values
=
aam
.
get_mean
(
points
)
...
...
@@ -128,7 +132,7 @@ def save_pca_model_shape(args):
def
reconstruct_with_model
(
args
):
assert
args
.
asf
,
'--asf
files should be given to allow the image to be shown'
assert
args
.
files
,
'--
files should be given to allow the image to be shown'
assert
args
.
model_shape_file
,
'--model_shape_file needs to be provided to get the pca model'
# clear sys args. arguments are conflicting with parseargs
...
...
@@ -154,11 +158,54 @@ def reconstruct_with_model(args):
app
.
run
()
def
show_pca_model
(
args
):
assert
args
.
model_shape_file
,
'--model_texture_file needs to be provided to save the pca model'
assert
args
.
model_texture_file
,
'--model_texture_file needs to be provided to save the pca model'
from
utils.triangles
import
draw_shape
,
draw_texture
Vt_shape
,
mean_values_shape
,
triangles
=
pca
.
load
(
args
.
model_shape_file
)
Vt_texture
,
mean_values_texture
,
_
=
pca
.
load
(
args
.
model_texture_file
)
image
=
np
.
full
((
480
,
640
,
3
),
fill_value
=
255
,
dtype
=
np
.
uint8
)
immPoints
=
imm
.
IMMPoints
(
filename
=
'data/imm_face_db/40-1m.asf'
)
input_image
=
immPoints
.
get_image
()
input_points
=
immPoints
.
get_points
()
h
,
w
,
c
=
input_image
.
shape
input_points
[:,
0
]
=
input_points
[:,
0
]
*
w
input_points
[:,
1
]
=
input_points
[:,
1
]
*
h
mean_values_shape
=
mean_values_shape
.
reshape
((
58
,
2
))
mean_values_shape
[:,
0
]
=
mean_values_shape
[:,
0
]
*
w
mean_values_shape
[:,
1
]
=
mean_values_shape
[:,
1
]
*
h
while
True
:
draw_texture
(
input_image
,
image
,
input_points
,
mean_values_shape
,
mean_values_texture
,
triangles
,
n_samples
=
80
)
draw_shape
(
image
,
mean_values_shape
,
triangles
,
multiply
=
False
)
cv2
.
imshow
(
'input_image'
,
input_image
)
cv2
.
imshow
(
'image'
,
image
)
k
=
cv2
.
waitKey
(
0
)
&
0xFF
if
k
==
27
:
break
i
+=
1
cv2
.
destroyAllWindows
()
def
main
():
"""main"""
parser
=
add_parser_options
()
args
=
parser
.
parse_args
()
if
args
.
save_pca_shape
:
if
args
.
show_pca
:
show_pca_model
(
args
)
elif
args
.
save_pca_shape
:
save_pca_model_shape
(
args
)
elif
args
.
save_pca_texture
:
save_pca_model_texture
(
args
)
...
...
src/utils/build/temp.macosx-10.11-x86_64-2.7/generate_head_texture.o
deleted
100644 → 0
View file @
265501fa
File deleted
src/utils/generate_head_texture.c
deleted
100644 → 0
View file @
265501fa
This diff is collapsed.
Click to expand it.
src/utils/generate_head_texture.pyx
View file @
88963c53
...
...
@@ -3,8 +3,10 @@ import numpy as np
cimport
numpy
as
np
from
cpython
cimport
array
as
c_array
DTYPE_Int
=
np
.
int
ctypedef
np
.
int_t
DTYPE_t
DTYPE_int
=
np
.
int
ctypedef
np
.
int_t
DTYPE_int_t
DTYPE_float
=
np
.
float32
ctypedef
np
.
float32_t
DTYPE_float_t
cdef
inline
float
cross_product
(
int
v1_x
,
int
v1_y
,
int
v2_x
,
int
v2_y
):
...
...
@@ -50,39 +52,77 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src,
def
get_colors_triangle
(
np
.
ndarray
[
unsigned
char
,
ndim
=
3
]
src
,
np
.
ndarray
[
unsigned
char
,
ndim
=
3
]
dst
,
int
x1
,
int
y1
,
int
x2
,
int
y2
,
int
x3
,
int
y3
):
np
.
ndarray
[
unsigned
char
,
ndim
=
3
]
dest
,
int
src_x1
,
int
src_y1
,
int
src_x2
,
int
src_y2
,
int
src_x3
,
int
src_y3
,
int
dest_x1
,
int
dest_y1
,
int
dest_x2
,
int
dest_y2
,
int
dest_x3
,
int
dest_y3
):
"""
Fill a triangle by applying the Barycentric Algorithm for deciding if a
point lies inside or outside a triangle.
"""
# Get the bounding box of the triangle
cdef
int
x_min
=
min
(
x1
,
min
(
x2
,
x3
))
cdef
int
x_max
=
max
(
x1
,
max
(
x2
,
x3
))
cdef
int
y_min
=
min
(
y1
,
min
(
y2
,
y3
))
cdef
int
y_max
=
max
(
y1
,
max
(
y2
,
y3
))
cdef
int
x_min
=
min
(
dest_x1
,
min
(
dest_x2
,
dest_
x3
))
cdef
int
x_max
=
max
(
dest_x1
,
max
(
dest_x2
,
dest_
x3
))
cdef
int
y_min
=
min
(
dest_y1
,
min
(
dest_y2
,
dest_
y3
))
cdef
int
y_max
=
max
(
dest_y1
,
max
(
dest_y2
,
dest_
y3
))
cdef
int
vs1_x
=
x2
-
x1
cdef
int
vs1_y
=
y2
-
y1
cdef
int
vs2_x
=
x3
-
x1
cdef
int
vs2_y
=
y3
-
y1
cdef
int
vs1_x
=
dest_x2
-
dest_
x1
cdef
int
vs1_y
=
dest_y2
-
dest_
y1
cdef
int
vs2_x
=
dest_x3
-
dest_
x1
cdef
int
vs2_y
=
dest_y3
-
dest_
y1
cdef
float
s
cdef
float
t
y_count
=
0
x_count
=
0
for
y
in
xrange
(
y_min
,
y_max
):
for
x
in
xrange
(
x_min
,
x_max
):
a
=
np
.
ndarray
([[
x1
,
x2
,
x3
],
[
y1
,
y2
,
y3
],
[
1
,
1
,
1
]],
dtype
=
DTYPE_Int
)
b
=
np
.
ndarray
([
x
,
y
,
1
],
dtype
=
DTYPE_Int
)
L
=
np
.
solve
(
a
,
b
)
#L[0]
#if s >= 0 and t >= 0 and s + t <= 1:
# dst[y_count * x_max + x_count] = src[y, x, :]
# y_count += 1
# x_count += 1
cdef
np
.
ndarray
L
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float
)
bary_centric_range
=
np
.
linspace
(
0
,
1
,
num
=
80
)
for
s_i
,
s
in
enumerate
(
bary_centric_range
):
for
t_i
,
t
in
enumerate
(
bary_centric_range
):
if
s
+
t
<=
1
:
a
=
np
.
array
([
[
src_x1
,
src_x2
,
src_x3
],
[
src_y1
,
src_y2
,
src_y3
],
[
1
,
1
,
1
]
])
L
[
0
]
=
s
L
[
1
]
=
t
L
[
2
]
=
1
-
s
-
t
src_loc
=
np
.
dot
(
a
,
L
)
a
=
np
.
array
([
[
dest_x1
,
dest_x2
,
dest_x3
],
[
dest_y1
,
dest_y2
,
dest_y3
],
[
1
,
1
,
1
]
])
dest_loc
=
np
.
dot
(
a
,
L
)
dest
[
dest_loc
[
1
][
0
],
dest_loc
[
0
][
0
],
:]
=
src
[
src_loc
[
1
][
0
],
src_loc
[
0
][
0
],
:]
# for y in xrange(y_min, y_max):
# for x in xrange(x_min, x_max):
# q_x = x - dest_x1
# q_y = y - dest_y1
# s = cross_product(q_x, q_y, vs2_x, vs2_y) / \
# cross_product(vs1_x, vs1_y, vs2_x, vs2_y)
# t = cross_product(vs1_x, vs1_y, q_x, q_y) / \
# cross_product(vs1_x, vs1_y, vs2_x, vs2_y)
# if s >= 0 and t >= 0 and s + t <= 1:
# a = np.array([
# [src_x1, src_x2, src_x3],
# [src_y1, src_y2, src_y3],
# [1, 1, 1]
# ])
# L[0] = s
# L[1] = t
# L[2] = 1 - s - t
# src_loc = np.dot(a, L)
# dest[y, x, :] = src[src_loc[1][0], src_loc[0][0], :]
src/utils/generate_head_texture.so
deleted
100755 → 0
View file @
265501fa
File deleted
src/utils/triangles.py
0 → 100644
View file @
88963c53
import
numpy
as
np
import
cv2
from
utils.generate_head_texture
import
fill_triangle
,
get_colors_triangle
def
cartesian2barycentric
(
r1
,
r2
,
r3
,
r
):
"""
Given a triangle spanned by three cartesion points
r1, r2, r2, and point r, return the barycentric weights l1, l2, l3.
Returns:
ndarray (of dim 3) weights of the barycentric coordinates
"""
x
,
y
=
r
x1
,
y1
=
r1
x2
,
y2
=
r2
x3
,
y3
=
r3
a
=
np
.
array
([[
x1
,
x2
,
x3
],
[
y1
,
y2
,
y3
],
[
1
,
1
,
1
]])
b
=
np
.
array
([
x
,
y
,
1
])
return
np
.
linalg
.
solve
(
a
,
b
)
def
barycentric2cartesian
(
r1
,
r2
,
r3
,
L
):
"""
Given the barycentric weights in L, and cartesian r1, r2, r3 coordinates of
points that span the triangle, return the cartesian coordinate of the
points that is located at the weights of L.
Returns:
ndarray [x,y] cartesian points.
"""
x1
,
y1
=
r1
x2
,
y2
=
r2
x3
,
y3
=
r3
a
=
np
.
array
([[
x1
,
x2
,
x3
],
[
y1
,
y2
,
y3
],
[
1
,
1
,
1
]])
b
=
np
.
array
(
L
)
return
np
.
asarray
(
np
.
dot
(
a
,
b
),
dtype
=
np
.
uint32
)
def
draw_shape
(
image
,
points
,
triangles
,
multiply
=
True
):
if
multiply
:
h
,
w
,
c
=
image
.
shape
points
[:,
0
]
=
points
[:,
0
]
*
w
points
[:,
1
]
=
points
[:,
1
]
*
h
dim
,
_
=
points
.
shape
point_indices
=
list
(
range
(
0
,
dim
))
for
t
,
tri
in
enumerate
(
triangles
):
p1
,
p2
,
p3
=
points
[
tri
]
cv2
.
line
(
image
,
tuple
(
p1
),
tuple
(
p2
),
(
255
,
0
,
100
),
1
)
cv2
.
line
(
image
,
tuple
(
p2
),
tuple
(
p3
),
(
255
,
0
,
100
),
1
)
cv2
.
line
(
image
,
tuple
(
p3
),
tuple
(
p1
),
(
255
,
0
,
100
),
1
)
for
i
,
p
in
enumerate
(
points
):
point_index
=
int
(
point_indices
[
i
])
cv2
.
putText
(
image
,
str
(
point_index
),
(
p
[
0
],
p
[
1
]),
cv2
.
FONT_HERSHEY_SIMPLEX
,
.
5
,
(
100
,
0
,
255
))
cv2
.
circle
(
image
,
tuple
(
p
),
3
,
color
=
(
0
,
255
,
100
))
def
draw_texture
(
src
,
dest
,
points2d_src
,
points2d_dest
,
texture
,
triangles
,
multiply
=
True
,
n_samples
=
20
):
texture
=
np
.
asarray
(
texture
,
dtype
=
np
.
uint8
).
reshape
((
-
1
,
3
))
for
t
,
tri
in
enumerate
(
triangles
):
src_p1
,
src_p2
,
src_p3
=
points2d_src
[
tri
]
dest_p1
,
dest_p2
,
dest_p3
=
points2d_dest
[
tri
]
get_colors_triangle
(
src
,
dest
,
src_p1
[
0
],
src_p1
[
1
],
src_p2
[
0
],
src_p2
[
1
],
src_p3
[
0
],
src_p3
[
1
],
dest_p1
[
0
],
dest_p1
[
1
],
dest_p2
[
0
],
dest_p2
[
1
],
dest_p3
[
0
],
dest_p3
[
1
]
)
src/view/reconstruct.py
View file @
88963c53
...
...
@@ -2,6 +2,7 @@ import kivy
kivy
.
require
(
'1.0.7'
)
import
numpy
as
np
import
cv2
from
kivy.app
import
App
from
kivy.uix.boxlayout
import
BoxLayout
...
...
@@ -12,6 +13,7 @@ from kivy.uix.slider import Slider
from
kivy.properties
import
ObjectProperty
from
kivy.uix.widget
import
Widget
from
kivy.graphics
import
Rectangle
,
Mesh
,
Line
,
Triangle
from
kivy.graphics.texture
import
Texture
from
kivy.graphics.instructions
import
InstructionGroup
from
kivy.graphics.context_instructions
import
Color
from
functools
import
partial
...
...
@@ -73,11 +75,46 @@ class ImageCanvas(Widget):
self
.
image
.
source
=
self
.
filename_image
self
.
canvas
.
ask_update
()
def
build_texture
(
self
,
r_texture
,
triangles
):
def
build_texture
(
self
,
r_
shape
,
r_
texture
,
triangles
):
self
.
texture
.
clear
()
image_width
,
image_height
=
self
.
get_rendered_size
()
self
.
triangles
.
add
(
Line
(
circle
=
(
100
,
200
,
10
)))
bary_centric_range
=
np
.
linspace
(
0
,
1
,
num
=
20
)
texture
=
Texture
.
create
(
size
=
(
image_width
,
image_height
),
colorfmt
=
'bgr'
)
buf
=
np
.
zeros
((
image_width
,
image_height
,
3
),
dtype
=
np
.
uint8
)
for
tri
in
triangles
[:
1
]:
points
=
r_shape
[
tri
]
pixels
=
r_texture
[
tri
].
reshape
((
-
1
,
3
))
x
=
points
[:,
0
]
*
image_width
+
self
.
get_image_left
(
image_width
)
y
=
(
1.0
-
points
[:,
1
])
*
image_height
+
self
.
get_image_bottom
(
image_height
)
p1
=
[
x
[
0
],
y
[
0
]]
p2
=
[
x
[
1
],
y
[
1
]]
p3
=
[
x
[
2
],
y
[
2
]]
L
=
np
.
zeros
((
3
,
1
))
for
s_i
,
s
in
enumerate
(
bary_centric_range
):
for
t_i
,
t
in
enumerate
(
bary_centric_range
):
if
s
+
t
<=
1
:
# build lambda's
L
[
0
]
=
s
L
[
1
]
=
t
L
[
2
]
=
1
-
s
-
t
cart_x
,
cart_y
,
_
=
aam
.
barycentric2cartesian
(
p1
,
p2
,
p3
,
L
)
buf
[
s_i
,
t_i
,
:]
=
pixels
[
s_i
*
20
+
t_i
,
:]
#buf = b''.join(map(chr, buf))
cv2
.
imshow
(
'image'
,
buf
)
cv2
.
waitKey
(
0
)
#texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte')
#self.texture.add(Rectangle(texture=texture, pos=(0, 100),
# size=(image_width, image_height)))
self
.
canvas
.
add
(
self
.
texture
)
self
.
canvas
.
ask_update
()
...
...
@@ -132,9 +169,9 @@ class RootWidget(BoxLayout):
def
__init__
(
self
,
**
kwargs
):
super
(
RootWidget
,
self
).
__init__
(
**
kwargs
)
self
.
images
=
kwargs
[
'args'
].
asf
self
.
files
=
kwargs
[
'args'
].
files
self
.
mean_values_shape
=
kwargs
[
'mean_values_shape'
]
self
.
mean_
texture_shap
e
=
kwargs
[
'mean_values_texture'
]
self
.
mean_
values_textur
e
=
kwargs
[
'mean_values_texture'
]
self
.
eigenv_shape
=
kwargs
[
'eigenv_shape'
]
self
.
eigenv_texture
=
kwargs
[
'eigenv_texture'
]
self
.
triangles
=
kwargs
[
'triangles'
]
...
...
@@ -146,7 +183,7 @@ class RootWidget(BoxLayout):
self
.
filename
=
''
image_slider
=
self
.
ids
[
'image_slider'
]
image_slider
.
max
=
len
(
self
.
imag
es
)
-
1
image_slider
.
max
=
len
(
self
.
fil
es
)
-
1
image_slider
.
bind
(
value
=
self
.
update_image
)
n_components_slider
=
self
.
ids
[
'n_components'
]
...
...
@@ -156,8 +193,8 @@ class RootWidget(BoxLayout):
self
.
ids
[
'image_viewer'
].
bind
(
size
=
self
.
on_resize
)
box_layout
=
self
.
ids
[
'eigenvalues'
]
self
.
landmark_list
=
aam
.
build
_feature_vectors
(
self
.
images
,
imm
.
get_imm_landmark
s
,
flattened
=
True
)
self
.
shape_list
=
aam
.
build_shape
_feature_vectors
(
self
.
files
,
imm
.
get_imm_point
s
,
flattened
=
True
)
for
c
in
range
(
self
.
n_components
):
slider
=
Slider
(
min
=-
10
,
max
=
10
,
value
=
0
,
id
=
str
(
c
))
...
...
@@ -165,25 +202,34 @@ class RootWidget(BoxLayout):
slider
.
bind
(
value
=
self
.
update_eigenvalues
)
def
reset_sliders
(
self
):
self
.
multipliers
=
np
.
ones
(
self
.
Vt
.
shape
[
1
])
self
.
multipliers
=
np
.
ones
(
self
.
eigenv_shape
.
shape
[
1
])
box_layout
=
self
.
ids
[
'eigenvalues'
]
for
c
in
box_layout
.
children
:
c
.
value
=
0
def
update_image_viewer
(
self
):
self
.
filename
=
self
.
imag
es
[
self
.
index
].
split
(
'.'
)[
0
]
+
'.jpg'
self
.
filename
=
self
.
fil
es
[
self
.
index
].
split
(
'.'
)[
0
]
+
'.jpg'
Vt_shape
=
np
.
dot
(
np
.
diag
(
self
.
multipliers
),
self
.
eigenv_shape
)
# Vt_texture = np.dot(np.diag(self.multipliers), self.eigenv_texture)
r_shape
=
pca
.
reconstruct
(
self
.
landmark
_list
[
self
.
index
],
Vt_shape
,
self
.
mean_values_shape
,
self
.
shape
_list
[
self
.
index
],
Vt_shape
,
self
.
mean_values_shape
,
n_components
=
self
.
n_components
).
reshape
((
-
1
,
2
))
# image = cv2.imread(self.filename)
# pixels = aam.sample_from_triangles(image, r_shape, self.triangles)
# pixels = np.ndarray.flatten(pixels)
# r_texture = pca.reconstruct(
# pixels, self.eigenv_texture, self.mean_values_texture,
# n_components=50000).reshape((95, -1))
# self.ids['image_viewer'].build_texture(r_shape, r_texture, self.triangles)
self
.
ids
[
'image_viewer'
].
update_rect
()
self
.
ids
[
'image_viewer'
].
update_image
(
self
.
filename
)
self
.
ids
[
'image_viewer'
].
build_line_grid
(
r_shape
,
self
.
triangles
)
# self.ids['image_viewer'].build_texture(r_shape, self.triangles)
def
on_resize
(
self
,
*
args
):
self
.
update_image_viewer
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment