From c6fa8a837ce346be2f701bca823a7d8db3eda56e Mon Sep 17 00:00:00 2001 From: Sugam Srivastava Date: Tue, 17 Mar 2020 17:41:00 +0530 Subject: [PATCH] #47 : Changed mbr to minimum_bounding_rectangle, Added opencv minimum_area_rectangle, Removed loop in mbr and substituted with in-built max and min functions --- doc/api.rst | 4 +-- pointpats/centrography.py | 48 ++++++++++++++++++++-------- pointpats/tests/test_centrography.py | 9 +++++- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/doc/api.rst b/doc/api.rst index ade5766..05cdbd0 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -34,8 +34,8 @@ Centrography .. autosummary:: :toctree: generated/ - - mbr + minimum_area_rectangle + minimum_bounding_rectangle hull mean_center weighted_mean_center diff --git a/pointpats/centrography.py b/pointpats/centrography.py index 19e2009..d208877 100644 --- a/pointpats/centrography.py +++ b/pointpats/centrography.py @@ -9,7 +9,7 @@ """ __author__ = "Serge Rey sjsrey@gmail.com" -__all__ = ['mbr', 'hull', 'mean_center', 'weighted_mean_center', +__all__ = ['minimum_area_rectangle', 'minimum_bounding_rectangle', 'hull', 'mean_center', 'weighted_mean_center', 'manhattan_median', 'std_distance', 'euclidean_median', 'ellipse', 'skyum', 'dtot',"_circle"] @@ -18,6 +18,7 @@ import numpy as np import warnings import copy +import cv2 as cv from math import pi as PI from scipy.spatial import ConvexHull from libpysal.cg import get_angle_between, Ray, is_clockwise @@ -27,10 +28,36 @@ not_clockwise = lambda x: not is_clockwise(x) MAXD = sys.float_info.max -MIND = sys.float_info.min +MIND = sys.float_info.minz +def minimum_area_rectangle(points): + """ + Find minimum area rectangle of a point array. + + Parameters + ---------- + points : arraylike + (n,2), (x,y) coordinates of a series of event points. + + Returns + ------- + min_x : float + leftmost value of the vertices of minimum bounding rectangle. + min_y : float + downmost value of the vertices of minimum bounding rectangle. + max_x : float + rightmost value of the vertices of minimum bounding rectangle. + max_y : float + upmost value of the vertices of minimum bounding rectangle. + + """ + points = np.array(points) + points = np.float32(points[:, np.newaxis, :]) + rect = cv.minAreaRect(points) + min_x, min_y, max_x, max_y = cv.boxPoints(rect) + return min_x, min_y, max_x, max_y -def mbr(points): +def minimum_bounding_rectangle(points): """ Find minimum bounding rectangle of a point array. @@ -54,16 +81,11 @@ def mbr(points): points = np.asarray(points) min_x = min_y = MAXD max_x = max_y = MIND - for point in points: - x, y = point - if x > max_x: - max_x = x - if x < min_x: - min_x = x - if y > max_y: - max_y = y - if y < min_y: - min_y = y + x, y = zip(*points) + min_x = min(x) + min_y = min(y) + max_x = max(x) + max_y = max(y) return min_x, min_y, max_x, max_y diff --git a/pointpats/tests/test_centrography.py b/pointpats/tests/test_centrography.py index 56ebbd1..14af710 100644 --- a/pointpats/tests/test_centrography.py +++ b/pointpats/tests/test_centrography.py @@ -15,8 +15,15 @@ def setUp(self): [79.26, 7.68], [8.23, 39.93], [98.73, 77.17], [89.78, 42.53], [65.19, 92.08], [54.46, 8.48]] + def test_centrography_mar(self): + min_x, min_y, max_x, max_y = minimum_area_rectangle(self.points) + np.testing.assert_array_almost_equal(min_x, [36.40165, 104.61744]) + np.testing.assert_array_almost_equal(min_y, [ 4.0872803, 30.417528 ]) + np.testing.assert_array_almost_equal(max_x, [75.599075, -0.7261505]) + np.testing.assert_array_almost_equal(max_y, [107.913445, 73.47376 ]) + def test_centrography_mbr(self): - min_x, min_y, max_x, max_y = mbr(self.points) + min_x, min_y, max_x, max_y = minimum_bounding_rectangle(self.points) np.testing.assert_allclose(min_x, 8.2300000000000004, RTOL) np.testing.assert_allclose(min_y, 7.6799999999999997, RTOL) np.testing.assert_allclose(max_x, 98.730000000000004, RTOL)