def test_init(self, level=1): g0 = Grid([0, 1], [0, 1]) g1 = Grid(2, 2) g2 = Grid([[0, 0], [1, 1]], [[0, 1], [0, 1]]) for g in [g0, g1, g2]: assert_array_almost_equal(g['cols'], np.array([[0, 1], [0, 1]])) assert_array_almost_equal(g['rows'], np.array([[0, 0], [1, 1]])) assert_array_almost_equal(g['z'], np.array([[1, 1], [1, 1]]))
def test_coords_readonly(self, level=2): g = Grid([0], [0]) try: g.coords = [] except AttributeError: pass else: fail("should not be able to set coords")
def test_coords(self, level=1): g = Grid([0], [0, 1, 2]) assert_array_almost_equal( g.coords, np.array([[[0, 0, 1], [1, 0, 1], [2, 0, 1]]])) g = Grid([0, 1], [0, 1]) assert_array_almost_equal( g.coords, np.array([[[0, 0, 1], [1, 0, 1]], [[0, 1, 1], [1, 1, 1]]]))
def mask_roi(rows, cols, bounds): """Return a mask for operating only on pixels inside the given bounds. Parameters ---------- rows, cols : int Shape of the target image. bounds : (M, 3) array of (x, y, 1) coordinates Boundary coordinates. """ # Sort corners clockwise. This can be done with a single # swap operation, but that's a bit more work. mask = (bounds < 1e-14) bounds[mask] -= 0.5 bounds[~mask] += 0.5 centroid = bounds.mean(axis=0) diff = bounds - centroid angle = np.arctan2(diff[:, 1], diff[:, 0]) bounds = bounds[np.argsort(angle)] bounds = np.vstack((bounds, bounds[0])) p = Polygon(bounds[:, 0], bounds[:, 1]) g = Grid(rows, cols) return p.inside(g['cols'].flat, g['rows'].flat).reshape(rows, cols)
def test_fields(self, level=1): g = Grid([0], [0]) assert_equal(g['cols'], g.cols)
def test_getitem(self, level=1): g = Grid([0], [0]) assert_array_almost_equal(g['cols'], np.array([[0]]))
def correspond(fA, A, fB, B, win_size=9): """Given coordinates of features in two images, determine possible correspondences using a Quantile-Quantile comparison. Parameters ---------- fA : list of tuple (x,y) Coordinates of the features in the source image. A : (m,n) ndarray of type uint8 Source image. fB : list of tuple (x,y) Coordinates of the features in the target image. A : (m,n) ndarray of type uint8 Target image. Returns ------- matches : list [((coord_source), (coord_target)), ...] """ # Ensure uneven window size win_size = int(win_size) win_size = win_size + ((win_size + 1) % 2) ## Used to round feature corners, used e.g. in LPT matching # Mask for removing corners r_max = ((win_size - 1) / 2.)**2 g = Grid(win_size, win_size) center = (win_size - 1) / 2. mask = (((g['cols'] - center)**2 + (g['rows'] - center)**2) > r_max) # Pre-calculate patches pA = {} angles = np.linspace(-np.pi, np.pi, 50) for (i, j) in fA: try: m, n, p, q = _safe_coord(i, j, A, win_size) except IndexError: pass else: patch = np.array(A[m:n, p:q], dtype=float) # patch[mask] = -1 # round feature pA[(i, j)] = patch pB = {} for (i, j) in fB: try: m, n, p, q = _safe_coord(i, j, B, win_size) except IndexError: pass else: patch = np.array(B[m:n, p:q], dtype=float) # patch[mask] = -1 # round feature pB[(i, j)] = patch count = 1 result_d = {} for (i, j) in fA: if count % 10 == 1: log.debug("%s/%s" % (count, len(fA))) count += 1 match_likelihood = -np.inf patch_A = pA.get((i, j), None) if patch_A is None: continue # Sort values for QQ-comparison patch_A = np.sort(patch_A) for (m, n) in fB: patch_B = pB.get((m, n), None) if patch_B is None: continue patch_B = np.sort(patch_B) norm = np.linalg.norm # A very counter-intuitive feature-matching scheme # that works. # |A - B| <= max(|A|, |B|) since all elements are positive order = 2 tmp = patch_B - patch_A tmp = -norm(tmp, order) / max(norm(patch_B, order), norm(patch_A, order)) if tmp > -0.5 and tmp > match_likelihood: match_likelihood = tmp result_d[(i, j)] = (m, n) # Get rid of features that occur twice in the mapping # There can be only one, after all reverse_d = {} for k, v in result_d.iteritems(): reverse_d[v] = reverse_d.get(v, []) reverse_d[v].append(k) for k, v in reverse_d.iteritems(): if len(v) > 1: for coord in v: del result_d[coord] return result_d.items()