Skip to content

Commit

Permalink
coverage now at 53%
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMariday committed Oct 13, 2024
1 parent 2e6e72f commit dbf0e29
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 69 deletions.
69 changes: 31 additions & 38 deletions marimapper/led_identifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,52 @@
from marimapper.led_map_2d import LEDDetection


class LedFinder:
def find_led_in_image(image, threshold=128):

def __init__(self, threshold=128):
self.threshold = threshold
_, image_thresh = cv2.threshold(image, threshold, 255, cv2.THRESH_TOZERO)

def find_led(self, image):
contours, _ = cv2.findContours(image_thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

_, image_thresh = cv2.threshold(image, self.threshold, 255, cv2.THRESH_TOZERO)
led_response_count = len(contours)
if led_response_count == 0:
return None

contours, _ = cv2.findContours(
image_thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE
)

led_response_count = len(contours)
if led_response_count == 0:
return None
moments = cv2.moments(image_thresh)

moments = cv2.moments(image_thresh)
img_height = image.shape[0]
img_width = image.shape[1]

img_height = image.shape[0]
img_width = image.shape[1]
center_u = moments["m10"] / max(moments["m00"], 0.00001)
center_v = moments["m01"] / max(moments["m00"], 0.00001)

center_u = moments["m10"] / max(moments["m00"], 0.00001)
center_v = moments["m01"] / max(moments["m00"], 0.00001)
center_u = center_u / img_width
v_offset = (img_width - img_height) / 2.0
center_v = (center_v + v_offset) / img_width

center_u = center_u / img_width
v_offset = (img_width - img_height) / 2.0
center_v = (center_v + v_offset) / img_width
return LEDDetection(center_u, center_v, contours)

return LEDDetection(center_u, center_v, contours)

@staticmethod
def draw_results(image, results):
def draw_led_detections(image, results):

render_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
render_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)

img_height = render_image.shape[0]
img_width = render_image.shape[1]
img_height = render_image.shape[0]
img_width = render_image.shape[1]

if results:
cv2.drawContours(render_image, results.contours, -1, (255, 0, 0), 1)
if results:
cv2.drawContours(render_image, results.contours, -1, (255, 0, 0), 1)

u_abs = int(results.u * img_width)
u_abs = int(results.u * img_width)

v_offset = (img_width - img_height) / 2.0
v_offset = (img_width - img_height) / 2.0

v_abs = int(results.v * img_width - v_offset)
v_abs = int(results.v * img_width - v_offset)

cv2.drawMarker(
render_image,
(u_abs, v_abs),
(0, 255, 0),
markerSize=100,
)
cv2.drawMarker(
render_image,
(u_abs, v_abs),
(0, 255, 0),
markerSize=100,
)

return render_image
return render_image
11 changes: 4 additions & 7 deletions marimapper/led_map_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def _load(self, filename):
if not os.path.exists(filename):
return False

if not filename.endswith(".csv"):
return False

with open(filename, "r") as f:
lines = f.readlines()

Expand All @@ -42,7 +45,7 @@ def _load(self, filename):
u = float(line[1])
v = float(line[2])
except (IndexError, ValueError):
logging.error(f"Failed to read line {i} of {filename}: {line}")
logging.warn(f"Failed to read line {i} of {filename}: {line}")
continue

self.add_detection(index, LEDDetection(u, v))
Expand Down Expand Up @@ -81,14 +84,8 @@ def get_all_2d_led_maps(directory):

for filename in sorted(os.listdir(directory)):

if not filename.endswith(".csv"):
continue

full_path = os.path.join(directory, filename)

if not os.path.isfile(full_path):
continue

led_map_2d = LEDMap2D(full_path)
if led_map_2d.valid:
led_maps_2d.append(led_map_2d)
Expand Down
6 changes: 0 additions & 6 deletions marimapper/led_map_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,6 @@ def rescale(self, target_inter_distance=1.0):
for cam in self.cameras:
cam[1] *= scale

def get_xyz_list(self):
return np.array([self[led_id]["pos"] for led_id in self.keys()])

def get_center(self):
return np.average(self.get_xyz_list(), axis=0)

def get_normal_list(self):
return np.array([self[led_id]["normal"] for led_id in self.keys()])

Expand Down
8 changes: 4 additions & 4 deletions marimapper/reconstructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from threading import Thread

from marimapper.camera import Camera, CameraSettings
from marimapper.led_identifier import LedFinder
from marimapper.led_identifier import find_led_in_image, draw_led_detections
from marimapper.timeout_controller import TimeoutController


Expand All @@ -26,7 +26,7 @@ def __init__(
self.dark_exposure = dark_exposure
self.light_exposure = self.cam.get_exposure()

self.led_finder = LedFinder(threshold)
self.threshold = threshold
self.timeout_controller = TimeoutController()

if width != -1 and height != -1:
Expand Down Expand Up @@ -101,10 +101,10 @@ def show_debug(self):
def find_led(self, debug=False):

image = self.cam.read()
results = self.led_finder.find_led(image)
results = find_led_in_image(image, self.threshold)

if debug:
rendered_image = self.led_finder.draw_results(image, results)
rendered_image = draw_led_detections(image, results)
cv2.imshow("MariMapper", rendered_image)
cv2.waitKey(1)

Expand Down
4 changes: 3 additions & 1 deletion marimapper/visualize_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ def reload_geometry__(self, first=False):
self.line_set.lines = open3d.utility.Vector2iVector(l)
self.line_set.colors = open3d.utility.Vector3dVector(c)

self.point_cloud.points = open3d.utility.Vector3dVector(led_map.get_xyz_list())
self.point_cloud.points = open3d.utility.Vector3dVector(
np.array([led_map.data[led_id]["pos"] for led_id in led_map.keys()])
)
self.point_cloud.normals = open3d.utility.Vector3dVector(
led_map.get_normal_list() * 0.2
)
Expand Down
62 changes: 62 additions & 0 deletions test/test_2d_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import tempfile
from marimapper.led_map_2d import LEDMap2D, get_all_2d_led_maps


def test_partially_valid_data():
temp_led_map_file = tempfile.NamedTemporaryFile(delete=False, suffix=".csv")
temp_led_map_file.write(
b"""index,u,v
0,0.379490,0.407710
2,0,0
2.2,0,0
bananas,apples,grapes
"""
)
temp_led_map_file.close()

led_map = LEDMap2D(filepath=temp_led_map_file.name)

assert led_map.valid

assert len(led_map) == 2

assert led_map.get_detection(0).pos() == (0.379490, 0.407710)

assert led_map.get_detection(2).pos() == (0, 0)


def test_invalid_path():

led_map = LEDMap2D(filepath="doesnt-exist-i-hope")
assert not led_map.valid


def test_get_all_maps():

directory = tempfile.TemporaryDirectory()

temp_led_map_file = tempfile.NamedTemporaryFile(
delete=False, suffix=".csv", dir=directory.name
)
temp_led_map_file.write(
b"""index,u,v
0,0.379490,0.407710
"""
)
temp_led_map_file.close()

temp_led_map_file_invalid = tempfile.NamedTemporaryFile(
delete=False, suffix=".html", dir=directory.name
)
temp_led_map_file_invalid.write(
b"""index,u,v
0,0.379490,0.407710
"""
)
temp_led_map_file_invalid.close()

all_maps = get_all_2d_led_maps(directory=directory.name)

assert len(all_maps) == 1

directory.cleanup()
44 changes: 44 additions & 0 deletions test/test_3d_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import tempfile
from marimapper.led_map_3d import LEDMap3D


def test_file_write():

led_id = 0
led_x = 0
led_y = 0
led_z = 0
led_x_normal = 1
led_y_normal = 1
led_z_normal = 1
led_error = 1

led_dict = {
"pos": (led_x, led_y, led_z),
"normal": (led_x_normal, led_y_normal, led_z_normal),
"error": led_error,
}

led_map = LEDMap3D({led_id: led_dict})

assert led_map.keys() == [led_id]

output_file = tempfile.NamedTemporaryFile(delete=False)

led_map.write_to_file(output_file.name)

with open(output_file.name) as f:
lines = f.readlines()

headings = ["index", "x", "y", "z", "xn", "yn", "zn", "error"]

assert lines[0].strip().split(",") == headings
data_line = lines[1].strip().split(",")
assert int(data_line[headings.index("index")]) == led_id
assert float(data_line[headings.index("x")]) == led_x
assert float(data_line[headings.index("y")]) == led_y
assert float(data_line[headings.index("z")]) == led_z
assert float(data_line[headings.index("xn")]) == led_x_normal
assert float(data_line[headings.index("yn")]) == led_y_normal
assert float(data_line[headings.index("zn")]) == led_z_normal
assert float(data_line[headings.index("error")]) == led_error
19 changes: 6 additions & 13 deletions test/test_led_identifier.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,34 @@
from marimapper.led_identifier import LedFinder
from marimapper.led_identifier import find_led_in_image, draw_led_detections
from marimapper.camera import Camera


def close(x, y):
return abs(x - y) < 0.000001


def test_init():
LedFinder()


def test_basic_image_loading():
led_finder = LedFinder()

mock_camera = Camera("test/MariMapper-Test-Data/9_point_box/cam_0/capture_0000.png")

detection = led_finder.find_led(mock_camera.read())
detection = find_led_in_image(mock_camera.read(color=False))
assert close(detection.u, 0.4029418361244019)
assert close(detection.v, 0.4029538809144072)


def test_none_found():
led_finder = LedFinder()

mock_camera = Camera("test/MariMapper-Test-Data/9_point_box/cam_0/capture_%04d.png")

for frame_id in range(24):
frame = mock_camera.read()
frame = mock_camera.read(color=False)
if frame_id in [7, 15, 23]:
led_results = led_finder.find_led(frame)
led_results = find_led_in_image(frame)
assert led_results is None


def test_draw_results():

led_finder = LedFinder()
mock_camera = Camera("test/MariMapper-Test-Data/9_point_box/cam_0/capture_%04d.png")
frame = mock_camera.read()
led_results = led_finder.find_led(frame)
led_finder.draw_results(frame, led_results)
led_results = find_led_in_image(frame)
draw_led_detections(frame, led_results)

0 comments on commit dbf0e29

Please sign in to comment.