Commit 88963c53 authored by Richard Torenvliet's avatar Richard Torenvliet

Make a way of showing the pca model getting the texture of the given image

parent 265501fa
data/* data/*
src/.cache/* src/.cache/*
src/utils/*.c
src/utils/*.o
src/utils/*.so
src/utils/build/
...@@ -14,35 +14,37 @@ data/imm_face_db.tar.gz: ...@@ -14,35 +14,37 @@ data/imm_face_db.tar.gz:
data/pca_shape_model.npy: data/pca_shape_model.npy:
python src/main.py \ python src/main.py \
--save_pca_shape \ --save_pca_shape \
--asf `./scripts/imm_train_set.sh` \ --files `./scripts/imm_train_set.sh` \
--model_shape_file data/pca_shape_model --model_shape_file data/pca_shape_model
data/pca_texture_model.npy: data/pca_texture_model.npy:
python src/main.py \ python src/main.py \
--save_pca_texture \ --save_pca_texture \
--asf `./scripts/imm_train_set.sh` \ --files `./scripts/imm_train_set.sh` \
--model_texture_file data/pca_texture_model \ --model_texture_file data/pca_texture_model \
--model_shape_file data/pca_shape_model.npy --model_shape_file data/pca_shape_model.npy
show_pca: show_pca:
python src/main.py \ python src/main.py \
--show_pca \ --show_pca \
--asf data/imm_face_db/*.asf \ --model_texture_file data/pca_texture_model.npy \
--model_shape_file data/pca_model.npy --model_shape_file data/pca_shape_model.npy
test_model: test_model:
python src/main.py \ python src/main.py \
--reconstruct \ --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 \ --model_shape_file data/pca_shape_model.npy \
--n_components 6 --n_components 6
show_reconstruction: show_reconstruction:
python src/main.py \ python src/main.py \
--reconstruct \ --reconstruct \
--asf data/imm_face_db/*.asf \ --files data/imm_face_db/*.asf \
--model_shape_file data/pca_shape_model.npy \
--model_texture_file data/pca_texture_model.npy \ --model_texture_file data/pca_texture_model.npy \
--model_shape_file data/pca_shape_model.npy \
--n_components 6 --n_components 6
test: test:
......
...@@ -5,7 +5,7 @@ SITE_PACKAGES := $(VIRTUALENV)/lib/$(PYTHON)/site-packages ...@@ -5,7 +5,7 @@ SITE_PACKAGES := $(VIRTUALENV)/lib/$(PYTHON)/site-packages
OPENCV:= $(SITE_PACKAGES)/cv.py $(SITE_PACKAGES)/cv2.so OPENCV:= $(SITE_PACKAGES)/cv.py $(SITE_PACKAGES)/cv2.so
TARGETS:= $(VIRTUALENV) data build TARGETS:= $(VIRTUALENV) data build utils
all: $(TARGETS) all: $(TARGETS)
include actions.mk include actions.mk
...@@ -13,6 +13,12 @@ include build.mk ...@@ -13,6 +13,12 @@ include build.mk
data: data/imm_face_db 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) build: $(OPENCV)
@(source $(VIRTUALENV)/bin/activate; \ @(source $(VIRTUALENV)/bin/activate; \
pip install -r requirements.txt; \ pip install -r requirements.txt; \
......
import logging import logging
from matplotlib.tri import Triangulation
import numpy as np import numpy as np
from matplotlib.tri import Triangulation
import cv2 import cv2
import pca
# local imports
import pca
from utils.generate_head_texture import fill_triangle, get_colors_triangle from utils.generate_head_texture import fill_triangle, get_colors_triangle
import utils.triangles as tu
logging.basicConfig(level=logging.INFO, logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(name)s: %(message)s') format='%(asctime)s %(levelname)s %(name)s: %(message)s')
...@@ -51,7 +52,7 @@ def get_triangles(x_vector, y_vector): ...@@ -51,7 +52,7 @@ def get_triangles(x_vector, y_vector):
return Triangulation(x_vector, y_vector).triangles 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 Gets the aam points from the files and appends them seperately to one
array. array.
...@@ -70,47 +71,14 @@ def build_feature_vectors(files, get_points, flattened=False): ...@@ -70,47 +71,14 @@ def build_feature_vectors(files, get_points, flattened=False):
return points return points
def cartesian2barycentric(r1, r2, r3, r): def sample_from_triangles(image, points2d, triangles, n_samples=20):
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):
all_triangles = [] all_triangles = []
h, w, c = b.shape h, w, c = image.shape
for tri in triangles: for tri in triangles:
p1_b = points2d_b[tri[0]] p1 = points2d[tri[0]]
p2_b = points2d_b[tri[1]] p2 = points2d[tri[1]]
p3_b = points2d_b[tri[2]] p3 = points2d[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)
bary_centric_range = np.linspace(0, 1, num=n_samples) bary_centric_range = np.linspace(0, 1, num=n_samples)
pixels = np.full((n_samples * n_samples, 3), fill_value=-1, dtype=np.int) 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): ...@@ -126,8 +94,8 @@ def sample_from_triangles(b, points2d_b, triangles, n_samples=20):
L[2] = 1 - s - t L[2] = 1 - s - t
# cartesian x, y coordinates inside the triangle # cartesian x, y coordinates inside the triangle
cart_x, cart_y, _ = barycentric2cartesian(p1_b, p2_b, p3_b, L) cart_x, cart_y, _ = tu.barycentric2cartesian(p1, p2, p3, L)
pixels[s_i * n_samples + t_i, :] = b[cart_y, cart_x, :] 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)) # 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): ...@@ -136,17 +104,27 @@ def sample_from_triangles(b, points2d_b, triangles, n_samples=20):
return np.asarray(all_triangles, dtype=np.uint8) 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 = [] 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[:10]): for i, f in enumerate(files[:1]):
image, landmarks = get_image_with_landmarks(f) image, landmarks = get_image_with_landmarks(f)
h, w, c = image.shape h, w, c = image.shape
landmarks[:, 0] = landmarks[:, 0] * w landmarks[:, 0] = landmarks[:, 0] * w
landmarks[:, 1] = landmarks[:, 1] * h landmarks[:, 1] = landmarks[:, 1] * h
triangles_colors = sample_from_triangles( triangles_colors = sample_from_triangles(
image, landmarks, triangles image, landmarks, triangles, n_samples=80
) )
mean_texture.append(triangles_colors) mean_texture.append(triangles_colors)
...@@ -158,7 +136,12 @@ def build_texture_feature_vector(files, get_image_with_landmarks, triangles): ...@@ -158,7 +136,12 @@ def build_texture_feature_vector(files, get_image_with_landmarks, triangles):
# if k == 27: # if k == 27:
# break # 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): def get_pixel_values(image, points):
...@@ -172,7 +155,6 @@ def get_pixel_values(image, points): ...@@ -172,7 +155,6 @@ def get_pixel_values(image, points):
hull = cv2.convexHull(points, returnPoints=True) hull = cv2.convexHull(points, returnPoints=True)
rect = cv2.boundingRect(hull) rect = cv2.boundingRect(hull)
pixels = []
x, y, w, h = rect x, y, w, h = rect
# pixels = np.zeros((h, w, c), dtype=np.uint8) # pixels = np.zeros((h, w, c), dtype=np.uint8)
...@@ -185,7 +167,6 @@ def get_pixel_values(image, points): ...@@ -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][0] = 0
image[y_loc_g][x_loc_g][1] = 0 image[y_loc_g][x_loc_g][1] = 0
image[y_loc_g][x_loc_g][2] = 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 np.asarray(pixels, dtype=np.uint8), hull
return image, hull return image, hull
...@@ -38,9 +38,9 @@ class IMMPoints(): ...@@ -38,9 +38,9 @@ class IMMPoints():
self.points = np.asarray(self.points, dtype='f') self.points = np.asarray(self.points, dtype='f')
def draw_triangles(self, img, points, multiply=True): def draw_triangles(self, image, points, multiply=True):
if multiply: if multiply:
h, w, c = img.shape h, w, c = image.shape
points[:, 0] = points[:, 0] * w points[:, 0] = points[:, 0] * w
points[:, 1] = points[:, 1] * h points[:, 1] = points[:, 1] * h
...@@ -50,30 +50,30 @@ class IMMPoints(): ...@@ -50,30 +50,30 @@ class IMMPoints():
for t, tri in enumerate(triangles.triangles): for t, tri in enumerate(triangles.triangles):
p1, p2, p3 = points[tri] p1, p2, p3 = points[tri]
cv2.line(img, tuple(p1), tuple(p2), (255, 0, 100), 1) cv2.line(image, tuple(p1), tuple(p2), (255, 0, 100), 1)
cv2.line(img, tuple(p2), tuple(p3), (255, 0, 100), 1) cv2.line(image, tuple(p2), tuple(p3), (255, 0, 100), 1)
cv2.line(img, tuple(p3), tuple(p1), (255, 0, 100), 1) cv2.line(image, tuple(p3), tuple(p1), (255, 0, 100), 1)
for i, p in enumerate(points): for i, p in enumerate(points):
point_index = int(point_indices[i]) point_index = int(point_indices[i])
cv2.putText(img, str(point_index), tuple((p[0], p[1])), cv2.putText(image, str(point_index), tuple((p[0], p[1])),
cv2.FONT_HERSHEY_SIMPLEX, .5, (100, 0, 255)) cv2.FONT_HERSHEY_SIMPLEX, .5, (100, 0, 255))
cv2.circle(img, tuple(p), 3, color=(0, 255, 100)) cv2.circle(image, tuple(p), 3, color=(0, 255, 100))
def show_on_img(self, img, window_name='image', multiply=True): def show_on_image(self, image, window_name='image', multiply=True):
self.draw_triangles(img, self.points, multiply=multiply) self.draw_triangles(image, self.points, multiply=multiply)
def show(self, window_name='image'): def show(self, window_name='image'):
"""show the image and datapoints on the image""" """show the image and datapoints on the image"""
assert(len(self.points) > 0) assert(len(self.points) > 0)
assert(len(self.filename) > 0) assert(len(self.filename) > 0)
img = self.get_image() image = self.get_image()
self.draw_triangles(img, self.points) self.draw_triangles(image, self.points)
def get_imm_landmarks(files): def get_imm_points(files):
points = [] points = []
for f in files: for f in files:
......
# python std
import argparse import argparse
import logging import logging
import sys import sys
# installed packages
import cv2
import numpy as np
# local imports # local imports
import pca import pca
import aam import aam
...@@ -36,9 +41,8 @@ def add_parser_options(): ...@@ -36,9 +41,8 @@ def add_parser_options():
help='Show and manipulate the saved PCA model' help='Show and manipulate the saved PCA model'
) )
# asf model_files
pca_group.add_argument( pca_group.add_argument(
'--asf', nargs='+', help='asf files to process' '--files', nargs='+', help='files to process'
) )
pca_group.add_argument( pca_group.add_argument(
...@@ -76,14 +80,14 @@ def save_pca_model_texture(args): ...@@ -76,14 +80,14 @@ def save_pca_model_texture(args):
mean_values = Vtm[1][0] 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_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, mean_values, triangles = pca.load(args.model_shape_file)
textures = aam.build_texture_feature_vector( textures = aam.build_texture_feature_vectors(
args.asf, imm.get_imm_image_with_landmarks, triangles args.files, imm.get_imm_image_with_landmarks, triangles, flattened=True
) )
mean_texture = aam.get_mean(textures) mean_texture = aam.get_mean(textures)
...@@ -110,11 +114,11 @@ def save_pca_model_shape(args): ...@@ -110,11 +114,11 @@ def save_pca_model_shape(args):
mean_values = Vtm[1][0] 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' assert args.model_shape_file, '--model_shape_file needs to be provided to save the pca model'
points = aam.build_feature_vectors(args.asf, points = aam.build_shape_feature_vectors(
imm.get_imm_landmarks, flattened=True) args.files, imm.get_imm_points, flattened=True)
mean_values = aam.get_mean(points) mean_values = aam.get_mean(points)
...@@ -128,7 +132,7 @@ def save_pca_model_shape(args): ...@@ -128,7 +132,7 @@ def save_pca_model_shape(args):
def reconstruct_with_model(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' 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 # clear sys args. arguments are conflicting with parseargs
...@@ -154,11 +158,54 @@ def reconstruct_with_model(args): ...@@ -154,11 +158,54 @@ def reconstruct_with_model(args):
app.run() 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(): def main():
"""main"""
parser = add_parser_options() parser = add_parser_options()
args = parser.parse_args() 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) save_pca_model_shape(args)
elif args.save_pca_texture: elif args.save_pca_texture:
save_pca_model_texture(args) save_pca_model_texture(args)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,8 +3,10 @@ import numpy as np ...@@ -3,8 +3,10 @@ import numpy as np
cimport numpy as np cimport numpy as np
from cpython cimport array as c_array from cpython cimport array as c_array
DTYPE_Int = np.int DTYPE_int = np.int
ctypedef np.int_t DTYPE_t 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): 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, ...@@ -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, def get_colors_triangle(np.ndarray[unsigned char, ndim=3] src,
np.ndarray[unsigned char, ndim=3] dst, np.ndarray[unsigned char, ndim=3] dest,
int x1, int y1, int x2, int y2, int x3, int y3): 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 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.
""" """
# Get the bounding box of the triangle # Get the bounding box of the triangle
cdef int x_min = min(x1, min(x2, x3)) cdef int x_min = min(dest_x1, min(dest_x2, dest_x3))
cdef int x_max = max(x1, max(x2, x3)) cdef int x_max = max(dest_x1, max(dest_x2, dest_x3))
cdef int y_min = min(y1, min(y2, y3)) cdef int y_min = min(dest_y1, min(dest_y2, dest_y3))
cdef int y_max = max(y1, max(y2, y3)) cdef int y_max = max(dest_y1, max(dest_y2, dest_y3))
cdef int vs1_x = x2 - x1 cdef int vs1_x = dest_x2 - dest_x1
cdef int vs1_y = y2 - y1 cdef int vs1_y = dest_y2 - dest_y1
cdef int vs2_x = x3 - x1 cdef int vs2_x = dest_x3 - dest_x1
cdef int vs2_y = y3 - y1 cdef int vs2_y = dest_y3 - dest_y1
cdef float s cdef float s
cdef float t cdef float t
y_count = 0 cdef np.ndarray L = np.zeros([3, 1], dtype=DTYPE_float)
x_count = 0
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): for s_i, s in enumerate(bary_centric_range):
a = np.ndarray([[x1, x2, x3], [y1, y2, y3], [1, 1, 1]], dtype=DTYPE_Int) for t_i, t in enumerate(bary_centric_range):
b = np.ndarray([x, y, 1], dtype=DTYPE_Int) if s + t <= 1:
L = np.solve(a, b) a = np.array([
[src_x1, src_x2, src_x3],
#L[0] [src_y1, src_y2, src_y3],
[1, 1, 1]
#if s >= 0 and t >= 0 and s + t <= 1: ])
# dst[y_count * x_max + x_count] = src[y, x, :]
# y_count += 1 L[0] = s
# x_count += 1 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], :]
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]
)
...@@ -2,6 +2,7 @@ import kivy ...@@ -2,6 +2,7 @@ import kivy
kivy.require('1.0.7') kivy.require('1.0.7')
import numpy as np import numpy as np
import cv2
from kivy.app import App from kivy.app import App
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
...@@ -12,6 +13,7 @@ from kivy.uix.slider import Slider ...@@ -12,6 +13,7 @@ from kivy.uix.slider import Slider
from kivy.properties import ObjectProperty from kivy.properties import ObjectProperty
from kivy.uix.widget import Widget from kivy.uix.widget import Widget
from kivy.graphics import Rectangle, Mesh, Line, Triangle from kivy.graphics import Rectangle, Mesh, Line, Triangle
from kivy.graphics.texture import Texture
from kivy.graphics.instructions import InstructionGroup from kivy.graphics.instructions import InstructionGroup
from kivy.graphics.context_instructions import Color from kivy.graphics.context_instructions import Color
from functools import partial from functools import partial
...@@ -73,11 +75,46 @@ class ImageCanvas(Widget): ...@@ -73,11 +75,46 @@ class ImageCanvas(Widget):
self.image.source = self.filename_image self.image.source = self.filename_image
self.canvas.ask_update() self.canvas.ask_update()
def build_texture(self, r_texture, triangles): def build_texture(self, r_shape, r_texture, triangles):
self.texture.clear() self.texture.clear()
image_width, image_height = self.get_rendered_size() 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.add(self.texture)
self.canvas.ask_update() self.canvas.ask_update()
...@@ -132,9 +169,9 @@ class RootWidget(BoxLayout): ...@@ -132,9 +169,9 @@ class RootWidget(BoxLayout):
def __init__(self, **kwargs): def __init__(self, **kwargs):
super(RootWidget, self).__init__(**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_values_shape = kwargs['mean_values_shape']
self.mean_texture_shape = kwargs['mean_values_texture'] self.mean_values_texture = kwargs['mean_values_texture']
self.eigenv_shape = kwargs['eigenv_shape'] self.eigenv_shape = kwargs['eigenv_shape']
self.eigenv_texture = kwargs['eigenv_texture'] self.eigenv_texture = kwargs['eigenv_texture']
self.triangles = kwargs['triangles'] self.triangles = kwargs['triangles']
...@@ -146,7 +183,7 @@ class RootWidget(BoxLayout): ...@@ -146,7 +183,7 @@ class RootWidget(BoxLayout):
self.filename = '' self.filename = ''
image_slider = self.ids['image_slider'] image_slider = self.ids['image_slider']
image_slider.max = len(self.images) - 1 image_slider.max = len(self.files) - 1
image_slider.bind(value=self.update_image) image_slider.bind(value=self.update_image)
n_components_slider = self.ids['n_components'] n_components_slider = self.ids['n_components']
...@@ -156,8 +193,8 @@ class RootWidget(BoxLayout): ...@@ -156,8 +193,8 @@ class RootWidget(BoxLayout):
self.ids['image_viewer'].bind(size=self.on_resize) self.ids['image_viewer'].bind(size=self.on_resize)
box_layout = self.ids['eigenvalues'] box_layout = self.ids['eigenvalues']
self.landmark_list = aam.build_feature_vectors( self.shape_list = aam.build_shape_feature_vectors(
self.images, imm.get_imm_landmarks, flattened=True) self.files, imm.get_imm_points, flattened=True)
for c in range(self.n_components): for c in range(self.n_components):
slider = Slider(min=-10, max=10, value=0, id=str(c)) slider = Slider(min=-10, max=10, value=0, id=str(c))
...@@ -165,25 +202,34 @@ class RootWidget(BoxLayout): ...@@ -165,25 +202,34 @@ class RootWidget(BoxLayout):
slider.bind(value=self.update_eigenvalues) slider.bind(value=self.update_eigenvalues)
def reset_sliders(self): 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'] box_layout = self.ids['eigenvalues']
for c in box_layout.children: for c in box_layout.children:
c.value = 0 c.value = 0
def update_image_viewer(self): def update_image_viewer(self):
self.filename = self.images[self.index].split('.')[0] + '.jpg' self.filename = self.files[self.index].split('.')[0] + '.jpg'
Vt_shape = np.dot(np.diag(self.multipliers), self.eigenv_shape) 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( 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 n_components=self.n_components
).reshape((-1, 2)) ).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_rect()
self.ids['image_viewer'].update_image(self.filename) self.ids['image_viewer'].update_image(self.filename)
self.ids['image_viewer'].build_line_grid(r_shape, self.triangles) 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): def on_resize(self, *args):
self.update_image_viewer() self.update_image_viewer()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment