From a7b2b94288c78b97322148ce24681c943f025ef6 Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Thu, 16 Jan 2020 17:33:51 -0800 Subject: [PATCH 01/11] fixed warpmatrix computation wrt to other references beside image 1 --- micasense/image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/micasense/image.py b/micasense/image.py index 80e8271..6005674 100644 --- a/micasense/image.py +++ b/micasense/image.py @@ -453,9 +453,9 @@ def get_homography(self,ref,R=None,T=None): R = rotations_degrees_to_rotation_matrix(self.rig_relatives) if T is None: T =np.zeros(3) - + R_ref = rotations_degrees_to_rotation_matrix(ref.rig_relatives) A = np.zeros((4,4)) - A[0:3,0:3]=R + A[0:3,0:3]=np.dot(R_ref.T,R) A[0:3,3]=T A[3,3]=1. C, _ = cv2.getOptimalNewCameraMatrix(self.cv2_camera_matrix(), From cbb940b4ec11a165d0b928e578c622c97cb4d94f Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 17 Jan 2020 10:48:18 -0800 Subject: [PATCH 02/11] added test for warp_matrices with different reference channels --- tests/test_capture.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/test_capture.py b/tests/test_capture.py index ce83ded..93771ca 100644 --- a/tests/test_capture.py +++ b/tests/test_capture.py @@ -25,6 +25,7 @@ import pytest import os, glob +import numpy as np import micasense.capture as capture import micasense.image as image @@ -278,3 +279,9 @@ def test_10_band_irradiance(flight_10band_rededge_capture): test_irradiance = flight_10band_rededge_capture.dls_irradiance() good_irradiance = [0.67305, 0.62855, 0.55658, 0.34257, 0.41591, 0.57470, 0.64203, 0.53739, 0.48215, 0.44563] assert test_irradiance == pytest.approx(good_irradiance, abs = 1e-5) + +def test_get_warp_matrices(test_capture): + for i in range(len(test_capture.images)): + w = test_capture.get_warp_matrices(i) + np.testing.assert_allclose(np.eye(3),w[i],atol=1e-6) + \ No newline at end of file From e6b5ce475c1e3cd877adb2c129717023c36a1c8e Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 17 Jan 2020 10:53:32 -0800 Subject: [PATCH 03/11] added test for warp_matrices with different reference channels --- tests/test_capture.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_capture.py b/tests/test_capture.py index 93771ca..75a5632 100644 --- a/tests/test_capture.py +++ b/tests/test_capture.py @@ -280,8 +280,8 @@ def test_10_band_irradiance(flight_10band_rededge_capture): good_irradiance = [0.67305, 0.62855, 0.55658, 0.34257, 0.41591, 0.57470, 0.64203, 0.53739, 0.48215, 0.44563] assert test_irradiance == pytest.approx(good_irradiance, abs = 1e-5) -def test_get_warp_matrices(test_capture): - for i in range(len(test_capture.images)): - w = test_capture.get_warp_matrices(i) +def test_get_warp_matrices(panel_altum_capture): + for i in range(len(panel_altum_capture.images)): + w = panel_altum_capture.get_warp_matrices(i) np.testing.assert_allclose(np.eye(3),w[i],atol=1e-6) \ No newline at end of file From d4d1ea7835966d039b48633d74fc4991d21e219d Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 6 Nov 2020 11:09:07 -0800 Subject: [PATCH 04/11] no changes yet --- tests/conftest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index ed767c1..ea48195 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -94,6 +94,7 @@ def non_panel_altum_capture(non_panel_altum_file_list): def panel_image_name(): image_path = os.path.join('data', '0000SET', '000') return os.path.join(image_path, 'IMG_0000_1.tif') + @pytest.fixture() def panel_image_name_red(): @@ -175,4 +176,4 @@ def panel_10band_rededge_capture(panel_10band_rededge_file_list): @pytest.fixture() def flight_10band_rededge_capture(flight_10band_rededge_file_list): - return capture.Capture.from_filelist(flight_10band_rededge_file_list) \ No newline at end of file + return capture.Capture.from_filelist(flight_10band_rededge_file_list) From 875d090fc8594051a53d75ed97fc17093bf0389a Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 6 Nov 2020 11:10:18 -0800 Subject: [PATCH 05/11] added relative tolerance for warp matrices of 1%, and absolute of 1px for warp and cropping test - this accomodates e.g. recent version changes of cv2 --- tests/test_imageutils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_imageutils.py b/tests/test_imageutils.py index ab0d0f5..cb864a3 100644 --- a/tests/test_imageutils.py +++ b/tests/test_imageutils.py @@ -85,9 +85,9 @@ def test_image_properties(non_panel_altum_capture): def test_warp_matrices(non_panel_altum_capture): warp_matrices = non_panel_altum_capture.get_warp_matrices() for index,warp_matrix in enumerate(warp_matrices): - assert(warp_matrix == pytest.approx(truth_warp_matrices[index])) + assert(warp_matrix == pytest.approx(truth_warp_matrices[index],rel=1e-2)) def test_cropping(non_panel_altum_capture): warp_matrices = non_panel_altum_capture.get_warp_matrices() cropped_dimensions,_ = imageutils.find_crop_bounds(non_panel_altum_capture,warp_matrices) - assert(cropped_dimensions == expected_dimensions) + assert(cropped_dimensions == pytest.approx(expected_dimensions,abs=1)) From 1f32d0f887ba97dbc2d4743f2b22eff9ec452220 Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 6 Nov 2020 11:11:05 -0800 Subject: [PATCH 06/11] added relative tolerance for warp matrices of 1%, and absolute of 1px for warp and cropping test - this accomodates e.g. recent version changes of cv2 sorted detected panel order, so test passes, irrespective of the order of detected panel corners --- tests/test_panel.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/test_panel.py b/tests/test_panel.py index 2706e6c..7366ee4 100644 --- a/tests/test_panel.py +++ b/tests/test_panel.py @@ -28,6 +28,7 @@ import math import micasense.image as image import micasense.panel as panel +import operator def test_qr_corners(panel_image_name): img = image.Image(panel_image_name) @@ -50,6 +51,10 @@ def test_panel_corners(panel_image_name): assert panel_pts is not None assert len(panel_pts) == len(good_pts) assert pan.serial == 'RP02-1603036-SC' + # the particular order of the points is not relevant + # so sort by coordinates + panel_pts = sorted(panel_pts,key=operator.itemgetter(0,1)) + good_pts = sorted(good_pts,key=operator.itemgetter(0,1)) for i, pt in enumerate(panel_pts): # different opencv/zbar versions round differently it seems assert pt[0] == pytest.approx(good_pts[i][0], abs=3) @@ -75,6 +80,8 @@ def test_raw_panel_manual(panel_image_name): assert num == pytest.approx(26005, rel=0.001) assert sat == pytest.approx(0, abs=2) + + def test_raw_panel(panel_image_name): img = image.Image(panel_image_name) pan = panel.Panel(img) @@ -128,7 +135,12 @@ def test_altum_panel(altum_panel_image_name): assert panel_pts is not None assert len(panel_pts) == len(good_pts) assert pan.serial == 'RP04-1901231-SC' - print(panel_pts) + + # the particular order of the points is not relevant + # so sort by coordinates + panel_pts = sorted(panel_pts,key=operator.itemgetter(0,1)) + good_pts = sorted(good_pts,key=operator.itemgetter(0,1)) + for i, pt in enumerate(panel_pts): # different opencv/zbar versions round differently it seems assert pt[0] == pytest.approx(good_pts[i][0], abs=3) From b07f5dad9cbed7e0092b8ebd31f688b9582f899f Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 6 Nov 2020 13:29:45 -0800 Subject: [PATCH 07/11] added set_raw(img) to allow writing to the objects raw image data --- micasense/image.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/micasense/image.py b/micasense/image.py index 6005674..3374ea2 100644 --- a/micasense/image.py +++ b/micasense/image.py @@ -214,7 +214,11 @@ def raw(self): print("Could not open image at path {}".format(self.path)) raise return self.__raw_image - + + def set_raw(self,img): + ''' set raw data from input img''' + self.__raw_image = img.astype(np.uint16) + def set_external_rig_relatives(self,external_rig_relatives): self.rig_translations = external_rig_relatives['rig_translations'] #external rig relatives are in rad From 5c927b77d9c223c86e07fd81b872bab6b965171a Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 6 Nov 2020 13:30:41 -0800 Subject: [PATCH 08/11] correct estimation of the number of saturated pixels , which also now computes and sets the saturated_panel_pixels_pct value for panel --- micasense/panel.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/micasense/panel.py b/micasense/panel.py index f8553e9..7e4b300 100644 --- a/micasense/panel.py +++ b/micasense/panel.py @@ -223,8 +223,10 @@ def region_stats(self, img, region, sat_threshold=None): mean_value = panel_pixels.mean() saturated_count = 0 if sat_threshold is not None: - saturated_px = np.asarray(np.where(panel_pixels > sat_threshold)) - saturated_count = saturated_px.sum() + saturated_count = (panel_pixels > sat_threshold).sum() + #set saturated pixels here + if num_pixels>0: + self.saturated_panel_pixels_pct = (100.0*saturated_count)/num_pixels return mean_value, stdev, num_pixels, saturated_count def raw(self): @@ -278,4 +280,4 @@ def plot(self, figsize=(14,14)): ax.imshow(display_img) plt.tight_layout() plt.show() - return fig, ax \ No newline at end of file + return fig, ax From 3c13b08f0d8fa2abf21676a726e8c54918838b66 Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 6 Nov 2020 13:31:11 -0800 Subject: [PATCH 09/11] test for the correct estimation of saturated panel pixels --- tests/test_panel.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/test_panel.py b/tests/test_panel.py index 7366ee4..8594697 100644 --- a/tests/test_panel.py +++ b/tests/test_panel.py @@ -80,7 +80,23 @@ def test_raw_panel_manual(panel_image_name): assert num == pytest.approx(26005, rel=0.001) assert sat == pytest.approx(0, abs=2) - +# test saturated pixels with modified panel picture +def test_raw_panel_saturatedl(panel_image_name): + img = image.Image(panel_image_name) + pan = panel.Panel(img,panelCorners=[[809, 613], [648, 615], [646, 454], [808, 452]]) + + #saturate 2500 pixels in the raw image - note that on the undistorted image this + #will result in 2329 saturated pixels + i0 = img.raw() + i0[500:550,700:750]=4095*16+1 + img.set_raw(i0) + + mean, std, num, sat = pan.raw() + print(mean,std,num,sat) + assert mean == pytest.approx(47245, rel=0.01) + assert std == pytest.approx(5846.1, rel=0.05) + assert num == pytest.approx(26005, rel=0.001) + assert sat == pytest.approx(2329, abs=0) def test_raw_panel(panel_image_name): img = image.Image(panel_image_name) From 70eb8a268e183f600f73517ca44a0b760c78758c Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 6 Nov 2020 14:43:17 -0800 Subject: [PATCH 10/11] added set_undistorted() function to modify the undistorted image --- micasense/image.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/micasense/image.py b/micasense/image.py index 3374ea2..ffb9479 100644 --- a/micasense/image.py +++ b/micasense/image.py @@ -216,9 +216,13 @@ def raw(self): return self.__raw_image def set_raw(self,img): - ''' set raw data from input img''' + ''' set raw image from input img''' self.__raw_image = img.astype(np.uint16) + def set_undistorted(self,img): + ''' set undistorted image from input img''' + self.__undistorted_image = img.astype(np.uint16) + def set_external_rig_relatives(self,external_rig_relatives): self.rig_translations = external_rig_relatives['rig_translations'] #external rig relatives are in rad From bb937cc0a2d02897de37067ac095fb2e5df7b2a2 Mon Sep 17 00:00:00 2001 From: Felix Darvas Date: Fri, 6 Nov 2020 14:43:57 -0800 Subject: [PATCH 11/11] test saturation on the undistorted image to be independent of cv2 , print from saturation test removed --- tests/test_panel.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test_panel.py b/tests/test_panel.py index 8594697..35d6990 100644 --- a/tests/test_panel.py +++ b/tests/test_panel.py @@ -87,16 +87,15 @@ def test_raw_panel_saturatedl(panel_image_name): #saturate 2500 pixels in the raw image - note that on the undistorted image this #will result in 2329 saturated pixels - i0 = img.raw() + i0 = img.undistorted(img.raw()) i0[500:550,700:750]=4095*16+1 - img.set_raw(i0) + img.set_undistorted(i0) mean, std, num, sat = pan.raw() - print(mean,std,num,sat) assert mean == pytest.approx(47245, rel=0.01) assert std == pytest.approx(5846.1, rel=0.05) assert num == pytest.approx(26005, rel=0.001) - assert sat == pytest.approx(2329, abs=0) + assert sat == pytest.approx(2500, abs=0) def test_raw_panel(panel_image_name): img = image.Image(panel_image_name)