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
3c33b0b3
Commit
3c33b0b3
authored
Jun 12, 2016
by
Richard Torenvliet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix building and 'reconstructing' mean texture from dataset
parent
e007d4c1
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
203 additions
and
106 deletions
+203
-106
src/aam.py
src/aam.py
+37
-40
src/main.py
src/main.py
+26
-14
src/pca.py
src/pca.py
+10
-8
src/utils/generate_head_texture.pyx
src/utils/generate_head_texture.pyx
+117
-31
src/utils/triangles.py
src/utils/triangles.py
+13
-13
No files found.
src/aam.py
View file @
3c33b0b3
...
@@ -5,7 +5,8 @@ import cv2
...
@@ -5,7 +5,8 @@ import cv2
# local imports
# local imports
import
pca
import
pca
from
utils.generate_head_texture
import
fill_triangle
,
get_colors_triangle
from
utils.generate_head_texture
import
fill_triangle
,
get_colors_triangle
,
\
get_row_colors_triangle
import
utils.triangles
as
tu
import
utils.triangles
as
tu
logging
.
basicConfig
(
level
=
logging
.
INFO
,
logging
.
basicConfig
(
level
=
logging
.
INFO
,
...
@@ -66,47 +67,40 @@ def build_shape_feature_vectors(files, get_points, flattened=False):
...
@@ -66,47 +67,40 @@ def build_shape_feature_vectors(files, get_points, flattened=False):
points
=
get_points
(
files
)
points
=
get_points
(
files
)
if
flattened
:
if
flattened
:
points
=
pca
.
flatten_feature_vectors
(
points
)
points
=
pca
.
flatten_feature_vectors
(
points
,
dim
=
0
)
return
points
return
points
def
sample_from_triangles
(
image
,
points2d
,
triangles
,
n_samples
=
80
):
def
sample_from_triangles
(
src
,
points2d_src
,
points2d_dst
,
triangles
):
all_triangles
=
[]
# texture = np.asarray(texture, dtype=np.uint8).reshape((-1, 3))
h
,
w
,
c
=
image
.
shape
triangles_pixels
=
[]
pixels
=
0
for
tri
in
triangles
:
for
tri
in
triangles
:
p1
=
points2d
[
tri
[
0
]]
src_p1
,
src_p2
,
src_p3
=
points2d_src
[
tri
]
p2
=
points2d
[
tri
[
1
]]
dst_p1
,
dst_p2
,
dst_p3
=
points2d_dst
[
tri
]
p3
=
points2d
[
tri
[
2
]]
dst
=
get_row_colors_triangle
(
bary_centric_range
=
np
.
linspace
(
0
,
1
,
num
=
n_samples
)
src
,
pixels
=
np
.
full
((
n_samples
*
n_samples
,
3
),
fill_value
=-
1
,
dtype
=
np
.
int
)
src_p1
[
0
],
src_p1
[
1
],
L
=
np
.
zeros
((
3
,
1
))
src_p2
[
0
],
src_p2
[
1
],
src_p3
[
0
],
src_p3
[
1
],
for
s_i
,
s
in
enumerate
(
bary_centric_range
):
dst_p1
[
0
],
dst_p1
[
1
],
for
t_i
,
t
in
enumerate
(
bary_centric_range
):
dst_p2
[
0
],
dst_p2
[
1
],
# make sure the coordinates are inside the triangle
dst_p3
[
0
],
dst_p3
[
1
]
if
s
+
t
<=
1
:
)
# build lambda's
L
[
0
]
=
s
L
[
1
]
=
t
L
[
2
]
=
1
-
s
-
t
# cartesian x, y coordinates inside the triangle
pixels
+=
dst
.
flatten
().
shape
[
0
]
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
))
triangles_pixels
.
extend
(
dst
.
flatten
(
))
all_triangles
.
append
(
pixels
[
np
.
where
(
pixels
>=
0
)]
)
result
=
np
.
asarray
(
triangles_pixels
,
dtype
=
np
.
uint8
)
return
np
.
asarray
(
all_triangles
,
dtype
=
np
.
uint8
)
return
result
def
build_texture_feature_vectors
(
files
,
get_image_with_landmarks
,
triangles
,
def
build_texture_feature_vectors
(
files
,
get_image_with_shape
,
mean_shape
,
triangles
):
flattened
=
True
):
mean_texture
=
[]
"""
"""
Args:
Args:
files (list): list files
files (list): list files
...
@@ -116,16 +110,22 @@ def build_texture_feature_vectors(files, get_image_with_landmarks, triangles,
...
@@ -116,16 +110,22 @@ def build_texture_feature_vectors(files, get_image_with_landmarks, triangles,
Returns:
Returns:
list: list of feature vectors
list: list of feature vectors
"""
"""
mean_texture
=
[]
for
i
,
f
in
enumerate
(
files
[:
1
]):
mean_shape_scaled
=
mean_shape
.
reshape
((
58
,
2
))
image
,
landmarks
=
get_image_with_landmarks
(
f
)
mean_shape_scaled
[:,
0
]
=
mean_shape_scaled
[:,
0
]
*
640
mean_shape_scaled
[:,
1
]
=
mean_shape_scaled
[:,
1
]
*
480
for
i
,
f
in
enumerate
(
files
):
image
,
shape
=
get_image_with_shape
(
f
)
h
,
w
,
c
=
image
.
shape
h
,
w
,
c
=
image
.
shape
landmarks
[:,
0
]
=
landmarks
[:,
0
]
*
w
landmarks
[:,
1
]
=
landmarks
[:,
1
]
*
h
shape
[:,
0
]
=
shape
[:,
0
]
*
w
shape
[:,
1
]
=
shape
[:,
1
]
*
h
triangles_colors
=
sample_from_triangles
(
triangles_colors
=
sample_from_triangles
(
image
,
landmarks
,
triangles
,
n_samples
=
80
image
,
shape
,
mean_shape_scaled
,
triangles
)
)
mean_texture
.
append
(
triangles_colors
)
mean_texture
.
append
(
triangles_colors
)
logger
.
info
(
'processed file: {} {}/{}'
.
format
(
f
,
i
,
len
(
files
)))
logger
.
info
(
'processed file: {} {}/{}'
.
format
(
f
,
i
,
len
(
files
)))
...
@@ -135,11 +135,8 @@ def build_texture_feature_vectors(files, get_image_with_landmarks, triangles,
...
@@ -135,11 +135,8 @@ def build_texture_feature_vectors(files, get_image_with_landmarks, triangles,
# if k == 27:
# if k == 27:
# break
# break
mean_texture
=
np
.
asarray
(
mean_texture
)
mean_texture
=
np
.
asarray
(
mean_texture
)
#mean_texture = pca.flatten_feature_vectors(mean_texture)
if
flattened
:
mean_texture
=
pca
.
flatten_feature_vectors
(
mean_texture
)
return
mean_texture
return
mean_texture
...
...
src/main.py
View file @
3c33b0b3
...
@@ -84,16 +84,17 @@ def save_pca_model_texture(args):
...
@@ -84,16 +84,17 @@ def save_pca_model_texture(args):
assert
args
.
model_shape_file
,
'--model_texture_file needs to be provided to save the pca model'
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'
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
)
Vt
,
s
,
mean_shape
,
triangles
=
pca
.
load
(
args
.
model_shape_file
)
textures
=
aam
.
build_texture_feature_vectors
(
textures
=
aam
.
build_texture_feature_vectors
(
args
.
files
,
imm
.
get_imm_image_with_landmarks
,
triangles
,
flattened
=
True
args
.
files
,
imm
.
get_imm_image_with_landmarks
,
mean_shape
,
triangles
)
)
mean_texture
=
aam
.
get_mean
(
textures
)
mean_texture
=
aam
.
get_mean
(
textures
)
_
,
_
,
Vt
=
pca
.
pca
(
textures
,
mean_texture
)
_
,
s
,
Vt
=
pca
.
pca
(
textures
,
mean_texture
)
pca
.
save
(
Vt
,
s
,
mean_texture
,
triangles
,
args
.
model_texture_file
)
pca
.
save
(
Vt
,
mean_texture
,
triangles
,
args
.
model_texture_file
)
logger
.
info
(
'texture pca model saved in %s'
,
args
.
model_texture_file
)
logger
.
info
(
'texture pca model saved in %s'
,
args
.
model_texture_file
)
...
@@ -122,12 +123,12 @@ def save_pca_model_shape(args):
...
@@ -122,12 +123,12 @@ def save_pca_model_shape(args):
mean_values
=
aam
.
get_mean
(
points
)
mean_values
=
aam
.
get_mean
(
points
)
_
,
_
,
Vt
=
pca
.
pca
(
points
,
mean_values
)
_
,
s
,
Vt
=
pca
.
pca
(
points
,
mean_values
)
mean_xy
=
mean_values
.
reshape
((
-
1
,
2
))
mean_xy
=
mean_values
.
reshape
((
-
1
,
2
))
triangles
=
aam
.
get_triangles
(
mean_xy
[:,
0
],
mean_xy
[:,
1
])
triangles
=
aam
.
get_triangles
(
mean_xy
[:,
0
],
mean_xy
[:,
1
])
pca
.
save
(
Vt
,
mean_values
,
triangles
,
args
.
model_shape_file
)
pca
.
save
(
Vt
,
s
,
mean_values
,
triangles
,
args
.
model_shape_file
)
logger
.
info
(
'shape pca model saved in %s'
,
args
.
model_shape_file
+
'_shape'
)
logger
.
info
(
'shape pca model saved in %s'
,
args
.
model_shape_file
+
'_shape'
)
...
@@ -164,14 +165,25 @@ def show_pca_model(args):
...
@@ -164,14 +165,25 @@ def show_pca_model(args):
from
utils.triangles
import
draw_shape
,
draw_texture
from
utils.triangles
import
draw_shape
,
draw_texture
Vt_shape
,
mean_values_shape
,
triangles
=
pca
.
load
(
args
.
model_shape_file
)
Vt_shape
,
s
,
mean_values_shape
,
triangles
=
pca
.
load
(
args
.
model_shape_file
)
Vt_texture
,
mean_values_texture
,
_
=
pca
.
load
(
args
.
model_texture_file
)
Vt_texture
,
s_texture
,
mean_values_texture
,
_
=
pca
.
load
(
args
.
model_texture_file
)
# calculate n_components which captures 90 percent of the variance
total
=
s_texture
.
sum
()
subtotal
=
0.0
i
=
0
while
(
subtotal
*
100.0
)
/
total
<=
90.0
:
subtotal
+=
s_texture
[
i
]
i
+=
1
n_components
=
i
image
=
np
.
full
((
480
,
640
,
3
),
fill_value
=
255
,
dtype
=
np
.
uint8
)
image
=
np
.
full
((
480
,
640
,
3
),
fill_value
=
255
,
dtype
=
np
.
uint8
)
imm
P
oints
=
imm
.
IMMPoints
(
filename
=
'data/imm_face_db/40-1m.asf'
)
imm
_p
oints
=
imm
.
IMMPoints
(
filename
=
'data/imm_face_db/40-1m.asf'
)
input_image
=
imm
P
oints
.
get_image
()
input_image
=
imm
_p
oints
.
get_image
()
input_points
=
imm
P
oints
.
get_points
()
input_points
=
imm
_p
oints
.
get_points
()
h
,
w
,
c
=
input_image
.
shape
h
,
w
,
c
=
input_image
.
shape
input_points
[:,
0
]
=
input_points
[:,
0
]
*
w
input_points
[:,
0
]
=
input_points
[:,
0
]
*
w
...
@@ -182,9 +194,9 @@ def show_pca_model(args):
...
@@ -182,9 +194,9 @@ def show_pca_model(args):
mean_values_shape
[:,
1
]
=
mean_values_shape
[:,
1
]
*
h
mean_values_shape
[:,
1
]
=
mean_values_shape
[:,
1
]
*
h
while
True
:
while
True
:
draw_texture
(
input_image
,
image
,
input_points
,
mean_values_shape
,
draw_texture
(
input_image
,
image
,
Vt_texture
,
input_points
,
mean_values_shape
,
mean_values_texture
,
triangles
,
n_samples
=
80
)
mean_values_texture
,
triangles
)
draw_shape
(
image
,
mean_values_shape
,
triangles
,
multiply
=
False
)
#
draw_shape(image, mean_values_shape, triangles, multiply=False)
cv2
.
imshow
(
'input_image'
,
input_image
)
cv2
.
imshow
(
'input_image'
,
input_image
)
cv2
.
imshow
(
'image'
,
image
)
cv2
.
imshow
(
'image'
,
image
)
...
...
src/pca.py
View file @
3c33b0b3
...
@@ -36,7 +36,7 @@ def reconstruct(feature_vector, Vt, mean_values, n_components=10):
...
@@ -36,7 +36,7 @@ def reconstruct(feature_vector, Vt, mean_values, n_components=10):
return
np
.
dot
(
Vt
[:
n_components
].
T
,
yk
)
+
mean_values
return
np
.
dot
(
Vt
[:
n_components
].
T
,
yk
)
+
mean_values
def
save
(
Vt
,
mean_values
,
triangles
,
filename
):
def
save
(
Vt
,
s
,
mean_values
,
triangles
,
filename
):
"""
"""
Store the U, s, Vt and mean of all the asf datafiles given by the asf
Store the U, s, Vt and mean of all the asf datafiles given by the asf
files.
files.
...
@@ -52,7 +52,7 @@ def save(Vt, mean_values, triangles, filename):
...
@@ -52,7 +52,7 @@ def save(Vt, mean_values, triangles, filename):
triangles = Vtm[2]
triangles = Vtm[2]
"""
"""
saving
=
np
.
asarray
([
Vt
,
[
mean_values
],
triangles
])
saving
=
np
.
asarray
([
Vt
,
s
,
[
mean_values
],
triangles
])
np
.
save
(
filename
,
saving
)
np
.
save
(
filename
,
saving
)
...
@@ -76,13 +76,14 @@ def load(filename):
...
@@ -76,13 +76,14 @@ def load(filename):
Vtm
=
np
.
load
(
filename
)
Vtm
=
np
.
load
(
filename
)
Vt
=
Vtm
[
0
]
Vt
=
Vtm
[
0
]
mean_values
=
Vtm
[
1
][
0
]
s
=
Vtm
[
1
]
triangles
=
Vtm
[
2
]
mean_values
=
Vtm
[
2
][
0
]
triangles
=
Vtm
[
3
]
return
Vt
,
mean_values
,
triangles
return
Vt
,
s
,
mean_values
,
triangles
def
flatten_feature_vectors
(
data
):
def
flatten_feature_vectors
(
data
,
dim
=
0
):
"""
"""
Flattens the feature vectors inside a ndarray
Flattens the feature vectors inside a ndarray
...
@@ -102,6 +103,7 @@ def flatten_feature_vectors(data):
...
@@ -102,6 +103,7 @@ def flatten_feature_vectors(data):
Args:
Args:
data (numpy array): array of feature vectors
data (numpy array): array of feature vectors
dim (int): dimension to flatten the data
return:
return:
array: (numpy array): array flattened feature vectors
array: (numpy array): array flattened feature vectors
...
@@ -109,9 +111,9 @@ def flatten_feature_vectors(data):
...
@@ -109,9 +111,9 @@ def flatten_feature_vectors(data):
"""
"""
flattened
=
[]
flattened
=
[]
rows
,
_
,
_
=
data
.
shape
n
=
data
.
shape
[
dim
]
for
i
in
range
(
rows
):
for
i
in
range
(
n
):
flattened
.
append
(
np
.
ndarray
.
flatten
(
data
[
i
]))
flattened
.
append
(
np
.
ndarray
.
flatten
(
data
[
i
]))
return
np
.
array
(
flattened
)
return
np
.
array
(
flattened
)
src/utils/generate_head_texture.pyx
View file @
3c33b0b3
...
@@ -18,6 +18,23 @@ cdef inline float cross_product(int v1_x, int v1_y, int v2_x, int v2_y):
...
@@ -18,6 +18,23 @@ cdef inline float cross_product(int v1_x, int v1_y, int v2_x, int v2_y):
return
(
v1_x
*
v2_y
)
-
(
v1_y
*
v2_x
)
return
(
v1_x
*
v2_y
)
-
(
v1_y
*
v2_x
)
cdef
inline
np
.
ndarray
[
double
,
ndim
=
1
]
cartesian2barycentric
(
int
r1_x
,
r1_y
,
int
r2_x
,
int
r2_y
,
int
r3_x
,
int
r3_y
,
int
r_x
,
int
r_y
):
"""
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
"""
a
=
np
.
array
([[
r1_x
,
r2_x
,
r3_x
],
[
r1_y
,
r2_y
,
r3_y
],
[
1
,
1
,
1
]])
b
=
np
.
array
([
r_x
,
r_y
,
1
])
return
np
.
linalg
.
solve
(
a
,
b
)
cdef
inline
np
.
ndarray
[
double
,
ndim
=
2
]
barycentric2cartesian
(
cdef
inline
np
.
ndarray
[
double
,
ndim
=
2
]
barycentric2cartesian
(
int
x1
,
int
x2
,
int
x3
,
int
y1
,
int
y2
,
int
y3
,
int
x1
,
int
x2
,
int
x3
,
int
y1
,
int
y2
,
int
y3
,
np
.
ndarray
[
long
,
ndim
=
2
]
matrix
,
np
.
ndarray
[
long
,
ndim
=
2
]
matrix
,
...
@@ -35,9 +52,10 @@ cdef inline np.ndarray[double, ndim=2] barycentric2cartesian(
...
@@ -35,9 +52,10 @@ cdef inline np.ndarray[double, ndim=2] barycentric2cartesian(
@
cython
.
boundscheck
(
False
)
@
cython
.
boundscheck
(
False
)
@
cython
.
wraparound
(
False
)
@
cython
.
wraparound
(
False
)
def
fill_triangle
(
np
.
ndarray
[
unsigned
char
,
ndim
=
3
]
src
,
def
fill_triangle
(
np
.
ndarray
[
unsigned
char
,
ndim
=
1
]
src
,
np
.
ndarray
[
unsigned
char
,
ndim
=
3
]
dst
,
np
.
ndarray
[
unsigned
char
,
ndim
=
3
]
dst
,
int
x1
,
int
y1
,
int
x2
,
int
y2
,
int
x3
,
int
y3
):
int
x1
,
int
y1
,
int
x2
,
int
y2
,
int
x3
,
int
y3
,
int
offset
,
int
index
):
"""
"""
Fill a triangle by applying the Barycentric Algorithm for deciding if a
Fill a triangle by applying the Barycentric Algorithm for deciding if a
point lies inside or outside a triangle.
point lies inside or outside a triangle.
...
@@ -49,26 +67,90 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src,
...
@@ -49,26 +67,90 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src,
cdef
int
y_min
=
min
(
y1
,
min
(
y2
,
y3
))
cdef
int
y_min
=
min
(
y1
,
min
(
y2
,
y3
))
cdef
int
y_max
=
max
(
y1
,
max
(
y2
,
y3
))
cdef
int
y_max
=
max
(
y1
,
max
(
y2
,
y3
))
cdef
int
vs1_x
=
x2
-
x1
cdef
np
.
ndarray
L
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float32
)
cdef
int
vs1_y
=
y2
-
y1
cdef
np
.
ndarray
matrix
=
np
.
full
([
3
,
3
],
fill_value
=
1
,
dtype
=
DTYPE_int
)
cdef
int
vs2_x
=
x3
-
x1
cdef
int
vs2_y
=
y3
-
y1
cdef
float
s
cdef
np
.
ndarray
src_loc
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float64
)
cdef
float
t
cdef
np
.
ndarray
dst_loc
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float64
)
for
y
in
xrange
(
y_min
,
y_max
):
cdef
int
w
=
x_max
-
x_min
for
x
in
xrange
(
x_min
,
x_max
):
cdef
int
h
=
y_max
-
y_min
q_x
=
x
-
x1
cdef
int
new_offset
q_y
=
y
-
y1
cdef
np
.
ndarray
src_reshaped
=
src
[
offset
:
offset
+
(
w
*
h
*
3
)].
reshape
((
h
,
w
,
3
))
#print src_reshaped
#print '(', w, '*', h, '*', 3, ') * ', ' = ', offset
for
j
,
y
in
enumerate
(
xrange
(
y_min
,
y_max
)):
for
i
,
x
in
enumerate
(
xrange
(
x_min
,
x_max
)):
dst_loc
=
cartesian2barycentric
(
x1
,
y1
,
x2
,
y2
,
x3
,
y3
,
x
,
y
)
s
=
dst_loc
[
0
]
t
=
dst_loc
[
1
]
# notice we have a soft margin of -0.00001, which makes sure there are no
# gaps due to rounding issues
if
s
>=
-
0.000000001
and
t
>=
-
0.000000001
and
s
+
t
<=
1.0
:
dst
[
y
,
x
,
:]
=
src_reshaped
[
j
,
i
,
:]
new_offset
=
(
w
*
h
*
3
)
return
new_offset
@
cython
.
boundscheck
(
False
)
@
cython
.
wraparound
(
False
)
def
get_row_colors_triangle
(
np
.
ndarray
[
unsigned
char
,
ndim
=
3
]
src
,
int
src_x1
,
int
src_y1
,
int
src_x2
,
int
src_y2
,
int
src_x3
,
int
src_y3
,
int
dst_x1
,
int
dst_y1
,
int
dst_x2
,
int
dst_y2
,
int
dst_x3
,
int
dst_y3
):
"""
Fill a triangle by applying the Barycentric Algorithm for deciding if a
point lies inside or outside a triangle.
"""
cdef
int
x_min
=
min
(
dst_x1
,
min
(
dst_x2
,
dst_x3
))
cdef
int
x_max
=
max
(
dst_x1
,
max
(
dst_x2
,
dst_x3
))
cdef
int
y_min
=
min
(
dst_y1
,
min
(
dst_y2
,
dst_y3
))
cdef
int
y_max
=
max
(
dst_y1
,
max
(
dst_y2
,
dst_y3
))
s
=
cross_product
(
q_x
,
q_y
,
vs2_x
,
vs2_y
)
/
\
cdef
np
.
ndarray
L
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float32
)
cross_product
(
vs1_x
,
vs1_y
,
vs2_x
,
vs2_y
)
cdef
np
.
ndarray
matrix
=
np
.
full
([
3
,
3
],
fill_value
=
1
,
dtype
=
DTYPE_int
)
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
:
cdef
np
.
ndarray
src_loc
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float64
)
dst
[
y
,
x
,
:]
=
src
[
y
,
x
,
:]
cdef
np
.
ndarray
dst_loc
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float64
)
cdef
np
.
ndarray
dst
=
np
.
full
(
[
y_max
-
y_min
,
x_max
-
x_min
,
3
],
fill_value
=
255
,
dtype
=
DTYPE_float64
)
for
j
,
y
in
enumerate
(
xrange
(
y_min
,
y_max
)):
for
i
,
x
in
enumerate
(
xrange
(
x_min
,
x_max
)):
dst_loc
=
cartesian2barycentric
(
dst_x1
,
dst_y1
,
dst_x2
,
dst_y2
,
dst_x3
,
dst_y3
,
x
,
y
)
s
=
dst_loc
[
0
]
t
=
dst_loc
[
1
]
# notice we have a soft margin of -0.00001, which makes sure there are no
# gaps due to rounding issues
if
s
>=
-
0.000001
and
t
>=
-
0.000001
and
s
+
t
<=
1.0
:
L
[
0
]
=
s
L
[
1
]
=
t
L
[
2
]
=
1
-
s
-
t
src_loc
=
barycentric2cartesian
(
src_x1
,
src_x2
,
src_x3
,
src_y1
,
src_y2
,
src_y3
,
matrix
,
L
)
dst
[
j
,
i
,
:]
=
src
[
src_loc
[
1
][
0
],
src_loc
[
0
][
0
],
:]
return
dst
@
cython
.
boundscheck
(
False
)
@
cython
.
boundscheck
(
False
)
...
@@ -83,6 +165,11 @@ def get_colors_triangle(np.ndarray[unsigned char, ndim=3] src,
...
@@ -83,6 +165,11 @@ def get_colors_triangle(np.ndarray[unsigned char, ndim=3] src,
Fill a triangle by applying the Barycentric Algorithm for deciding if a
Fill a triangle by applying the Barycentric Algorithm for deciding if a
point lies inside or outside a triangle.
point lies inside or outside a triangle.
"""
"""
cdef
int
x_min
=
min
(
dst_x1
,
min
(
dst_x2
,
dst_x3
))
cdef
int
x_max
=
max
(
dst_x1
,
max
(
dst_x2
,
dst_x3
))
cdef
int
y_min
=
min
(
dst_y1
,
min
(
dst_y2
,
dst_y3
))
cdef
int
y_max
=
max
(
dst_y1
,
max
(
dst_y2
,
dst_y3
))
cdef
float
s
cdef
float
s
cdef
float
t
cdef
float
t
...
@@ -92,12 +179,18 @@ def get_colors_triangle(np.ndarray[unsigned char, ndim=3] src,
...
@@ -92,12 +179,18 @@ def get_colors_triangle(np.ndarray[unsigned char, ndim=3] src,
cdef
np
.
ndarray
src_loc
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float64
)
cdef
np
.
ndarray
src_loc
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float64
)
cdef
np
.
ndarray
dst_loc
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float64
)
cdef
np
.
ndarray
dst_loc
=
np
.
zeros
([
3
,
1
],
dtype
=
DTYPE_float64
)
cdef
np
.
ndarray
bary_centric_range
=
np
.
linspace
(
0
,
1
,
num
=
80
)
for
y
in
xrange
(
y_min
,
y_max
):
for
x
in
xrange
(
x_min
,
x_max
):
dst_loc
=
cartesian2barycentric
(
dst_x1
,
dst_y1
,
dst_x2
,
dst_y2
,
dst_x3
,
dst_y3
,
x
,
y
)
s
=
dst_loc
[
0
]
t
=
dst_loc
[
1
]
# get a float value for every pixel
# notice we have a soft margin of -0.00001, which makes sure there are no
for
s
in
bary_centric_range
:
# gaps due to rounding issues
for
t
in
bary_centric_range
:
if
s
>=
-
0.000001
and
t
>=
-
0.000001
and
s
+
t
<=
1.0
:
if
s
+
t
<=
1
:
L
[
0
]
=
s
L
[
0
]
=
s
L
[
1
]
=
t
L
[
1
]
=
t
L
[
2
]
=
1
-
s
-
t
L
[
2
]
=
1
-
s
-
t
...
@@ -109,11 +202,4 @@ def get_colors_triangle(np.ndarray[unsigned char, ndim=3] src,
...
@@ -109,11 +202,4 @@ def get_colors_triangle(np.ndarray[unsigned char, ndim=3] src,
L
L
)
)
dst_loc
=
barycentric2cartesian
(
dst
[
y
,
x
,
:]
=
src
[
src_loc
[
1
][
0
],
src_loc
[
0
][
0
],
:]
dst_x1
,
dst_x2
,
dst_x3
,
dst_y1
,
dst_y2
,
dst_y3
,
matrix
,
L
)
dst
[
dst_loc
[
1
][
0
],
dst_loc
[
0
][
0
],
:]
=
src
[
src_loc
[
1
][
0
],
src_loc
[
0
][
0
],
:]
src/utils/triangles.py
View file @
3c33b0b3
...
@@ -67,20 +67,20 @@ def draw_shape(image, points, triangles, multiply=True):
...
@@ -67,20 +67,20 @@ def draw_shape(image, points, triangles, multiply=True):
cv2
.
circle
(
image
,
tuple
(
p
),
3
,
color
=
(
0
,
255
,
100
))
cv2
.
circle
(
image
,
tuple
(
p
),
3
,
color
=
(
0
,
255
,
100
))
def
draw_texture
(
src
,
dest
,
points2d_src
,
points2d_dest
,
texture
,
def
draw_texture
(
src
,
dest
,
Vt
,
points2d_src
,
points2d_dst
,
texture
,
triangles
):
triangles
,
multiply
=
True
,
n_samples
=
20
):
# texture = np.asarray(texture, dtype=np.uint8).reshape((-1, 3))
texture
=
np
.
asarray
(
texture
,
dtype
=
np
.
uint8
).
reshape
((
-
1
,
3
))
texture
=
np
.
asarray
(
texture
,
np
.
uint8
)
offset
=
0
for
t
,
tri
in
enumerate
(
triangles
):
for
t
,
tri
in
enumerate
(
triangles
):
src_p1
,
src_p2
,
src_p3
=
points2d_src
[
tri
]
src_p1
,
src_p2
,
src_p3
=
points2d_src
[
tri
]
dest_p1
,
dest_p2
,
dest_p3
=
points2d_dest
[
tri
]
dst_p1
,
dst_p2
,
dst_p3
=
points2d_dst
[
tri
]
get_colors_triangle
(
offset
+=
fill_triangle
(
src
,
dest
,
texture
,
dest
,
src_p1
[
0
],
src_p1
[
1
],
dst_p1
[
0
],
dst_p1
[
1
],
src_p2
[
0
],
src_p2
[
1
],
dst_p2
[
0
],
dst_p2
[
1
],
src_p3
[
0
],
src_p3
[
1
],
dst_p3
[
0
],
dst_p3
[
1
],
dest_p1
[
0
],
dest_p1
[
1
],
offset
,
dest_p2
[
0
],
dest_p2
[
1
],
t
dest_p3
[
0
],
dest_p3
[
1
]
)
)
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