Commit e007d4c1 authored by Richard Torenvliet's avatar Richard Torenvliet

Update copying a color from a triangle

parent 88963c53
data/* data/*
src/.cache/* src/.cache/*
src/*/.cache
src/utils/*.c src/utils/*.c
src/utils/*.o src/utils/*.o
src/utils/*.so src/utils/*.so
......
...@@ -49,3 +49,6 @@ show_reconstruction: ...@@ -49,3 +49,6 @@ show_reconstruction:
test: test:
python -m py.test -f src/*_test.py python -m py.test -f src/*_test.py
test_modules:
python -m py.test -f src/*/*_test.py
...@@ -5,21 +5,19 @@ SITE_PACKAGES := $(VIRTUALENV)/lib/$(PYTHON)/site-packages ...@@ -5,21 +5,19 @@ 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 utils TARGETS:= $(OPENCV) $(VIRTUALENV) data utils
all: $(TARGETS) all: $(TARGETS)
include actions.mk include actions.mk
include build.mk
data: data/imm_face_db data: data/imm_face_db
utils: generate_head_texture.so utils: generate_head_texture.so
generate_head_texture.so: src/utils/generate_head_texture.pyx generate_head_texture.so: src/utils/generate_head_texture.pyx
(cd src/utils; python setup.py build_ext --inplace) (cd src/utils; python setup.py build_ext --inplace)
build: $(OPENCV) build: requirements.txt
@(source $(VIRTUALENV)/bin/activate; \ @(source $(VIRTUALENV)/bin/activate; \
pip install -r requirements.txt; \ pip install -r requirements.txt; \
); );
......
...@@ -71,7 +71,7 @@ def build_shape_feature_vectors(files, get_points, flattened=False): ...@@ -71,7 +71,7 @@ def build_shape_feature_vectors(files, get_points, flattened=False):
return points return points
def sample_from_triangles(image, points2d, triangles, n_samples=20): def sample_from_triangles(image, points2d, triangles, n_samples=80):
all_triangles = [] all_triangles = []
h, w, c = image.shape h, w, c = image.shape
......
import numpy as np import numpy as np
import cv2
import pytest
import imm_points import imm_points
import cv2
import aam import aam
import pca import pca
...@@ -44,6 +45,7 @@ def test_zero_mean_aan(): ...@@ -44,6 +45,7 @@ def test_zero_mean_aan():
np.testing.assert_array_equal(zero_mean, expected) np.testing.assert_array_equal(zero_mean, expected)
@pytest.mark.skipif(True, reason='not suitable for pytest')
def test_get_pixel_values(): def test_get_pixel_values():
asf_file = '../data/imm_face_db/40-2m.asf' asf_file = '../data/imm_face_db/40-2m.asf'
imm = imm_points.IMMPoints(filename=asf_file) imm = imm_points.IMMPoints(filename=asf_file)
...@@ -54,6 +56,7 @@ def test_get_pixel_values(): ...@@ -54,6 +56,7 @@ def test_get_pixel_values():
pixels, hull = aam.get_pixel_values(image, points) pixels, hull = aam.get_pixel_values(image, points)
@pytest.mark.skipif(True, reason='not suitable for pytest')
def test_sample_from_triangles(): def test_sample_from_triangles():
blue_points = [[20, 20], [50, 160], [160, 20], blue_points = [[20, 20], [50, 160], [160, 20],
[50, 20], [60, 200], [180, 20]] [50, 20], [60, 200], [180, 20]]
......
...@@ -193,8 +193,6 @@ def show_pca_model(args): ...@@ -193,8 +193,6 @@ def show_pca_model(args):
if k == 27: if k == 27:
break break
i += 1
cv2.destroyAllWindows() cv2.destroyAllWindows()
......
...@@ -5,14 +5,34 @@ from cpython cimport array as c_array ...@@ -5,14 +5,34 @@ from cpython cimport array as c_array
DTYPE_int = np.int DTYPE_int = np.int
ctypedef np.int_t DTYPE_int_t ctypedef np.int_t DTYPE_int_t
DTYPE_float = np.float32
ctypedef np.float32_t DTYPE_float_t DTYPE_float32 = np.float32
DTYPE_float64 = np.float64
ctypedef np.float32_t DTYPE_float32_t
ctypedef np.float64_t DTYPE_float64_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):
# Cross product of two 2d vectors # Cross product of two 2d vectors
return (v1_x * v2_y) - (v1_y * v2_x) return (v1_x * v2_y) - (v1_y * v2_x)
cdef inline np.ndarray[double, ndim=2] barycentric2cartesian(
int x1, int x2, int x3, int y1, int y2, int y3,
np.ndarray[long, ndim=2] matrix,
np.ndarray[float, ndim=2] Lambdas):
matrix[0][0] = x1
matrix[0][1] = x2
matrix[0][2] = x3
matrix[1][0] = y1
matrix[1][1] = y2
matrix[1][2] = y3
return np.dot(matrix, Lambdas)
@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=3] src,
...@@ -51,78 +71,49 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src, ...@@ -51,78 +71,49 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src,
dst[y, x, :] = src[y, x, :] dst[y, x, :] = src[y, x, :]
@cython.boundscheck(False)
@cython.wraparound(False)
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] dest, np.ndarray[unsigned char, ndim=3] dst,
int src_x1, int src_y1, int src_x2, int src_y2, int int src_x1, int src_y1, int src_x2, int src_y2,
src_x3, int src_y3, int src_x3, int src_y3,
int dest_x1, int dest_y1, int dest_x2, int dest_y2, int int dst_x1, int dst_y1, int dst_x2, int dst_y2,
dest_x3, int dest_y3): int dst_x3, int dst_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
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 = 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 s
cdef float t cdef float t
cdef np.ndarray L = np.zeros([3, 1], dtype=DTYPE_float) cdef np.ndarray L = np.zeros([3, 1], dtype=DTYPE_float32)
cdef np.ndarray matrix = np.full([3, 3], fill_value=1, dtype=DTYPE_int)
bary_centric_range = np.linspace(0, 1, num=80) cdef np.ndarray src_loc = np.zeros([3, 1], dtype=DTYPE_float64)
cdef np.ndarray dst_loc = np.zeros([3, 1], dtype=DTYPE_float64)
for s_i, s in enumerate(bary_centric_range): cdef np.ndarray bary_centric_range = np.linspace(0, 1, num=80)
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]
])
# get a float value for every pixel
for s in bary_centric_range:
for t in bary_centric_range:
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
src_loc = np.dot(a, L) src_loc = barycentric2cartesian(
src_x1, src_x2, src_x3,
a = np.array([ src_y1, src_y2, src_y3,
[dest_x1, dest_x2, dest_x3], matrix,
[dest_y1, dest_y2, dest_y3], L
[1, 1, 1] )
])
dst_loc = barycentric2cartesian(
dest_loc = np.dot(a, L) dst_x1, dst_x2, dst_x3,
dest[dest_loc[1][0], dest_loc[0][0], :] = src[src_loc[1][0], src_loc[0][0], :] dst_y1, dst_y2, dst_y3,
matrix,
# for y in xrange(y_min, y_max): L
# for x in xrange(x_min, x_max): )
# q_x = x - dest_x1
# q_y = y - dest_y1 dst[dst_loc[1][0], dst_loc[0][0], :] = src[src_loc[1][0], src_loc[0][0], :]
# 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
import utils.generate_head_texture as ht
import time
blue_image = cv2.imread('data/test_data/blue.png')
red_image = cv2.imread('data/test_data/red.png')
def test_get_colors_triangle():
src = blue_image
dst = red_image
points2d_src = np.array([
[20, 20], [50, 160], [160, 20],
[50, 20], [60, 200], [180, 20]
])
points2d_dst = np.array([
[40, 80], [130, 150], [40, 150],
[40, 80], [60, 82], [60, 100]
])
triangles = [[0, 1, 2]]
t1 = time.clock()
for i in range(10):
for t, tri in enumerate(triangles):
src_p1, src_p2, src_p3 = points2d_src[tri]
dst_p1, dst_p2, dst_p3 = points2d_dst[tri]
ht.get_colors_triangle(
src, dst,
src_p1[0], src_p1[1],
src_p2[0], src_p2[1],
src_p3[0], src_p3[1],
dst_p1[0], dst_p1[1],
dst_p2[0], dst_p2[1],
dst_p3[0], dst_p3[1]
)
print (time.clock() - t1) / 10.
#cv2.imshow('blue_image', blue_image)
#cv2.imshow('red_image', red_image)
#cv2.waitKey(0)
assert False
...@@ -5,10 +5,10 @@ from distutils.extension import Extension ...@@ -5,10 +5,10 @@ from distutils.extension import Extension
from Cython.Build import cythonize from Cython.Build import cythonize
extensions = [ extensions = [
Extension( Extension(
"generate_head_texture", 'generate_head_texture',
["generate_head_texture.pyx"], ['generate_head_texture.pyx'],
include_dirs=[np.get_include()], include_dirs=[np.get_include()], )
)] ]
setup( setup(
ext_modules=cythonize(extensions), ext_modules=cythonize(extensions),
......
...@@ -67,8 +67,9 @@ def draw_shape(image, points, triangles, multiply=True): ...@@ -67,8 +67,9 @@ 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, triangles, multiply=True, n_samples=20): def draw_texture(src, dest, points2d_src, points2d_dest, texture,
texture = np.asarray(texture, dtype=np.uint8).reshape((-1, 3)) triangles, multiply=True, n_samples=20):
texture = np.asarray(texture, dtype=np.uint8).reshape((-1, 3))
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]
......
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