Skip to content

Commit

Permalink
Merge pull request #177 from OpenPTV/dry_run
Browse files Browse the repository at this point in the history
This is the same as previous pull request
  • Loading branch information
alexlib authored Mar 25, 2019
2 parents 72c745f + daf3d21 commit 35416bd
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 50 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ script:
- python setup.py install
- cd test
- nosetests --verbose

3 changes: 3 additions & 0 deletions liboptv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
cmake_minimum_required(VERSION 2.8)
set (CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set (CMAKE_INSTALL_RPATH "$ORIGIN/../lib:$ORIGIN/")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/")
project(OpenPTV)
# enable_testing()
Expand Down
76 changes: 72 additions & 4 deletions py_bind/optv/correspondences.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import numpy as np

from optv.transforms cimport pixel_to_metric, dist_to_flat
from optv.parameters cimport ControlParams, VolumeParams
from optv.calibration cimport Calibration, calibration
from optv.calibration cimport Calibration
from optv.orientation cimport COORD_UNUSED
from optv.tracking_framebuf cimport TargetArray, Target, target, frame, \
PT_UNUSED, CORRES_NONE
Expand Down Expand Up @@ -145,9 +145,15 @@ def correspondences(list img_pts, list flat_coords, list cals,
num_targs - total number of targets (must be greater than the sum of
previous 3).
"""
cdef:
cdef:
int num_cams = len(cals)


# Special case of a single camera, follow the single_cam_correspondence docstring
if num_cams == 1:
sorted_pos, sorted_corresp, num_targs = single_cam_correspondence(img_pts, flat_coords, cals)
return sorted_pos, sorted_corresp, num_targs

cdef:
calibration **calib = <calibration **> malloc(
num_cams * sizeof(calibration *))
coord_2d **corrected = <coord_2d **> malloc(
Expand Down Expand Up @@ -180,7 +186,7 @@ def correspondences(list img_pts, list flat_coords, list cals,
sorted_corresp = [None]*(num_cams - 1)
last_count = 0

for clique_type in xrange(num_cams - 1):
for clique_type in range(num_cams - 1):
num_points = match_counts[4 - num_cams + clique_type] # for 1-4 cameras
clique_targs = np.full((num_cams, num_points, 2), PT_UNUSED,
dtype=np.float64)
Expand Down Expand Up @@ -216,3 +222,65 @@ def correspondences(list img_pts, list flat_coords, list cals,
free(corresp_buf) # Note this for future returning of correspondences.

return sorted_pos, sorted_corresp, num_targs

def single_cam_correspondence(list img_pts, list flat_coords, list cals):
"""
Single camera correspondence is not a real correspondence, it will be only a projection
of a 2D target from the image space into the 3D position, x,y,z using epi_mm_2d
function. Here we only update the pointers of the targets and return it in a proper format.
Arguments:
img_pts - a list of c := len(cals), containing TargetArray objects, each
with the target coordinates of n detections in the respective image.
The target arrays are clobbered: returned arrays have the tnr property
set. the pnr property should be set to the target index in its array.
flat_coords - a list of MatchedCoordinates objects, one per camera, holding
the x-sorted flat-coordinates conversion of the respective image
targets.
cals - a list of Calibration objects, each for the camera taking one image.
Returns:
sorted_pos - a tuple of (c,?,2) arrays, each with the positions in each of
c image planes of points belonging to quadruplets, triplets, pairs
found.
sorted_corresp - a tuple of (c,?) arrays, each with the point identifiers
of targets belonging to a quad/trip/etc per camera.
num_targs - total number of targets (must be greater than the sum of
previous 3).
"""
cdef:
int pt, num_points
coord_2d *corrected = <coord_2d *> malloc(sizeof(coord_2d *))

corrected = (<MatchedCoords>flat_coords[0]).buf

sorted_pos = [None]
sorted_corresp = [None]

num_points = len(img_pts[0])

clique_targs = np.full((1, num_points, 2), PT_UNUSED,
dtype=np.float64)
clique_ids = np.full((1, num_points), CORRES_NONE,
dtype=np.int_)

# Trace back the pixel target properties through the flat metric
# intermediary that's x-sorted.
for pt in range(num_points):

# From Beat code (issue #118) pix[0][geo[0][i].pnr].tnr=i;

p1 = corrected[pt].pnr
clique_ids[0, pt] = p1

if p1 > -1:
targ = img_pts[0][p1]
clique_targs[0, pt, 0] = (<Target> targ)._targ.x
clique_targs[0, pt, 1] = (<Target> targ)._targ.x
# we also update the tnr, see docstring of correspondences
(<Target> targ)._targ.tnr = pt

sorted_pos[0] = clique_targs
sorted_corresp[0] = clique_ids

return sorted_pos, sorted_corresp, num_points
2 changes: 2 additions & 0 deletions py_bind/optv/orientation.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ cdef extern from "optv/orientation.h":

double point_position(vec2d targets[], int num_cams, mm_np *multimed_pars,
calibration* cals[], vec3d res);
double single_cam_point_position(vec2d targets[], int num_cams, mm_np *multimed_pars,
calibration* cals[], vec3d res);
int raw_orient(calibration* cal, control_par *cpar, int nfix, vec3d fix[],
target pix[]);
double* orient (calibration* cal_in, control_par *cpar, int nfix,
Expand Down
81 changes: 75 additions & 6 deletions py_bind/optv/orientation.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ from libc.stdlib cimport calloc, free

from optv.tracking_framebuf cimport TargetArray
from optv.calibration cimport Calibration
from optv.parameters cimport ControlParams
from optv.parameters cimport ControlParams, VolumeParams
from optv.epipolar cimport epi_mm_2D


def match_detection_to_ref(Calibration cal,
np.ndarray[ndim=2, dtype=pos_t] ref_pts,
Expand Down Expand Up @@ -34,11 +36,9 @@ def match_detection_to_ref(Calibration cal,
Returns:
TargetArray holding the sorted targets.
"""
# This was a very restrictive constraint that we removed
# to make the calibration feasible
#
# if len(img_pts) < len(ref_pts):
# raise ValueError('Must have at least as many targets as ref. points.')

if len(img_pts) < len(ref_pts):
raise ValueError('Must have at least as many targets as ref. points.')

cdef:
vec3d *ref_coord
Expand Down Expand Up @@ -70,6 +70,75 @@ cdef calibration** cal_list2arr(list cals):
return calib

def point_positions(np.ndarray[ndim=3, dtype=pos_t] targets,
ControlParams cparam, cals, VolumeParams vparam):
"""
Calculate the 3D positions of the points given by their 2D projections
using one of the options:
- for a single camera, uses single_cam_point_positions()
- for multiple cameras, uses multi_cam_point_positions()
Arguments:
np.ndarray[ndim=3, dtype=pos_t] targets - (num_targets, num_cams, 2) array,
containing the metric coordinates of each target on the image plane of
each camera. Cameras must be in the same order for all targets.
ControlParams cparam - needed for the parameters of the tank through which
we see the targets.
cals - a sequence of Calibration objects for each of the cameras, in the
camera order of ``targets``.
VolumeParams vparam - an object holding observed volume size parameters, needed
for the single camera case only.
Returns:
res - (n,3) array for n points represented by their targets.
rcm - n-length array, the Ray Convergence Measure for eachpoint for multi camera
option, or zeros for a single camera option
"""
cdef:
np.ndarray[ndim=2, dtype=pos_t] res
np.ndarray[ndim=1, dtype=pos_t] rcm

if len(cals) == 1:
res, rcm = single_cam_point_positions(targets, cparam, cals, vparam)
elif len(cals) > 1:
res, rcm = multi_cam_point_positions(targets,cparam,cals)
else:
raise ValueError("wrong number of cameras in point_positions")

return res, rcm


def single_cam_point_positions(np.ndarray[ndim=3, dtype=pos_t] targets,
ControlParams cparam, cals, VolumeParams vparam):
"""
Calculates the 3D positions of the points from a single camera using
the 2D target positions given in metric coordinates
"""
cdef:
np.ndarray[ndim=2, dtype=pos_t] res
np.ndarray[ndim=1, dtype=pos_t] rcm
np.ndarray[ndim=2, dtype=pos_t] targ
calibration ** calib = cal_list2arr(cals)
int cam, num_cams

# So we can address targets.data directly instead of get_ptr stuff:
targets = np.ascontiguousarray(targets)

num_targets = targets.shape[0]
num_cams = targets.shape[1]
res = np.empty((num_targets, 3))
rcm = np.zeros(num_targets)

for pt in range(num_targets):
targ = targets[pt]
epi_mm_2D (targ[0][0], targ[0][1],
calib[0], cparam._control_par.mm, vparam._volume_par,
<vec3d> np.PyArray_GETPTR2(res, pt, 0));

return res, rcm


def multi_cam_point_positions(np.ndarray[ndim=3, dtype=pos_t] targets,
ControlParams cparam, cals):
"""
Calculate the 3D positions of the points given by their 2D projections.
Expand Down
80 changes: 40 additions & 40 deletions py_bind/test/test_corresp.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,51 +80,51 @@ def test_full_corresp(self):
mc = MatchedCoords(targs, cpar, cal)
corrected.append(mc)

sorted_pos, sorted_corresp, num_targs = correspondences(
_, _, num_targs = correspondences(
img_pts, corrected, cals, vpar, cpar)
self.failUnlessEqual(num_targs, 16)

def test_single_cam_corresp(self):
"""Single camera correspondence"""
cpar = ControlParams(1)
cpar.read_control_par("testing_fodder/single_cam/parameters/ptv.par")
vpar = VolumeParams()
vpar.read_volume_par("testing_fodder/single_cam/parameters/criteria.par")

# Cameras are at so high angles that opposing cameras don't see each
# other in the normal air-glass-water setting.
cpar.get_multimedia_params().set_layers([1.], [1.])
cpar.get_multimedia_params().set_n3(1.)
"""Single camera correspondence"""
cpar = ControlParams(1)
cpar.read_control_par("testing_fodder/single_cam/parameters/ptv.par")
vpar = VolumeParams()
vpar.read_volume_par("testing_fodder/single_cam/parameters/criteria.par")

# Cameras are at so high angles that opposing cameras don't see each
# other in the normal air-glass-water setting.
cpar.get_multimedia_params().set_layers([1.], [1.])
cpar.get_multimedia_params().set_n3(1.)

cals = []
img_pts = []
corrected = []
cal = Calibration()
cal.from_file(
"testing_fodder/single_cam/calibration/cam_1.tif.ori",
"testing_fodder/single_cam/calibration/cam_1.tif.addpar")
cals.append(cal)

# Generate test targets.
targs = TargetArray(9)
for row, col in np.ndindex(3, 3):
targ_ix = row*3 + col
targ = targs[targ_ix]

cals = []
img_pts = []
corrected = []
cal = Calibration()
cal.from_file(
"testing_fodder/single_cam/calibration/cam_1.tif.ori",
"testing_fodder/single_cam/calibration/cam_1.tif.addpar")
cals.append(cal)
pos3d = 10*np.array([[col, row, 0]], dtype=np.float64)
pos2d = image_coordinates(
pos3d, cal, cpar.get_multimedia_params())
targ.set_pos(convert_arr_metric_to_pixel(pos2d, cpar)[0])

# Generate test targets.
targs = TargetArray(9)
for row, col in np.ndindex(3, 3):
targ_ix = row*3 + col
targ = targs[targ_ix]

pos3d = 10*np.array([[col, row, 0]], dtype=np.float64)
pos2d = image_coordinates(
pos3d, cal, cpar.get_multimedia_params())
targ.set_pos(convert_arr_metric_to_pixel(pos2d, cpar)[0])

targ.set_pnr(targ_ix)
targ.set_pixel_counts(25, 5, 5)
targ.set_sum_grey_value(10)

img_pts.append(targs)
mc = MatchedCoords(targs, cpar, cal)
corrected.append(mc)
targ.set_pnr(targ_ix)
targ.set_pixel_counts(25, 5, 5)
targ.set_sum_grey_value(10)

sorted_pos, sorted_corresp, num_targs = correspondences(
img_pts, corrected, cals, vpar, cpar)
img_pts.append(targs)
mc = MatchedCoords(targs, cpar, cal)
corrected.append(mc)

_, _, num_targs = correspondences(
img_pts, corrected, cals, vpar, cpar)

self.failUnlessEqual(num_targs, 9)
self.failUnlessEqual(num_targs, 9)

0 comments on commit 35416bd

Please sign in to comment.