From 32acedb9c3a5f569903401bb55144cfc98ac24c6 Mon Sep 17 00:00:00 2001 From: fabienlombard <48451783+fabienlombard@users.noreply.github.com> Date: Sat, 8 Feb 2025 21:43:19 +0100 Subject: [PATCH 1/7] Update __init__.py trial to correct the segmenter --- .../segmenter/planktoscope/segmenter/__init__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/processing/segmenter/planktoscope/segmenter/__init__.py b/processing/segmenter/planktoscope/segmenter/__init__.py index d9641f0..4d905e4 100644 --- a/processing/segmenter/planktoscope/segmenter/__init__.py +++ b/processing/segmenter/planktoscope/segmenter/__init__.py @@ -601,11 +601,12 @@ def _pipe(self, ecotaxa_export): # TODO check image list here to find if a flat exists # we recalculate the flat every 10 pictures if recalculate_flat: - recalculate_flat = False + self.segmenter_client.client.publish( "status/segmenter", '{"status":"Calculating flat"}' ) if images_count < 10: + recalculate_flat = False self._calculate_flat( images_list[0:images_count], images_count, self.__working_path ) @@ -632,11 +633,12 @@ def _pipe(self, ecotaxa_export): # we recalculate the flat if the heuristics detected we should if recalculate_flat: # not i % 10 and i < (images_count - 10) - recalculate_flat = False - if len(images_list) == 10: - # We are too close to the end of the list, take the previous 10 images instead of the next 10 + + if len(images_list) <= 10: + # there is too few images : take whatever exists flat = self._calculate_flat(images_list, 10, self.__working_path) elif i > (len(images_list) - 11): + recalculate_flat = False # We are too close to the end of the list, take the previous 10 images instead of the next 10 flat = self._calculate_flat( images_list[i - 10 : i], 10, self.__working_path From 1600192c19c9944ad68f40ed564bc66c4d9ae268 Mon Sep 17 00:00:00 2001 From: fabienlombard <48451783+fabienlombard@users.noreply.github.com> Date: Sun, 9 Feb 2025 09:32:00 +0100 Subject: [PATCH 2/7] Update __init__.py This is an optimisation attempt to calculate the flat on only 5 images and to do it every 15 images only (not always). This way the calculation should be way lighter --- .../planktoscope/segmenter/__init__.py | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/processing/segmenter/planktoscope/segmenter/__init__.py b/processing/segmenter/planktoscope/segmenter/__init__.py index 4d905e4..50d7736 100644 --- a/processing/segmenter/planktoscope/segmenter/__init__.py +++ b/processing/segmenter/planktoscope/segmenter/__init__.py @@ -66,7 +66,7 @@ # Note(ethanjli): if/when we start having more env vars, we may want to start using the `environs` # package from PyPI for more structured parsing of env vars: SUBTRACT_CONSECUTIVE_MASKS = os.getenv( - "SEGMENTER_PIPELINE_SUBTRACT_CONSECUTIVE_MASKS", "False" + "SEGMENTER_PIPELINE_SUBTRACT_CONSECUTIVE_MASKS", "True" ).lower() in ("true", "1", "t") if SUBTRACT_CONSECUTIVE_MASKS: logger.info( @@ -599,19 +599,20 @@ def _pipe(self, ecotaxa_export): average_objects = 0 recalculate_flat = True # TODO check image list here to find if a flat exists - # we recalculate the flat every 10 pictures + # we recalculate the flat on 5 images every 15 pictures (time optimisation) + count_recalculateflat=0 if recalculate_flat: self.segmenter_client.client.publish( "status/segmenter", '{"status":"Calculating flat"}' ) - if images_count < 10: + if images_count < 5: recalculate_flat = False self._calculate_flat( images_list[0:images_count], images_count, self.__working_path ) else: - self._calculate_flat(images_list[0:10], 10, self.__working_path) + self._calculate_flat(images_list[0:5], 5, self.__working_path) if self.__save_debug_img: self._save_image( @@ -630,22 +631,27 @@ def _pipe(self, ecotaxa_export): "status/segmenter", f'{{"status":"Segmenting image {filename}, image {i+1}/{images_count}"}}', ) + count_recalculateflat=count_recalculateflat+1 + if count_recalculateflat==15: + count_recalculateflat=0 + recalculate_flat = True # we recalculate the flat if the heuristics detected we should - if recalculate_flat: # not i % 10 and i < (images_count - 10) + if recalculate_flat: # not i % 5 and i < (images_count - 5) - if len(images_list) <= 10: + if len(images_list) <= 5: # there is too few images : take whatever exists - flat = self._calculate_flat(images_list, 10, self.__working_path) - elif i > (len(images_list) - 11): + flat = self._calculate_flat(images_list, images_count, self.__working_path) + elif i > (len(images_list) - 6): recalculate_flat = False # We are too close to the end of the list, take the previous 10 images instead of the next 10 flat = self._calculate_flat( - images_list[i - 10 : i], 10, self.__working_path + images_list[i - 5 : i], 5, self.__working_path ) else: + recalculate_flat = False flat = self._calculate_flat( - images_list[i : i + 10], 10, self.__working_path + images_list[i : i + 5], 5, self.__working_path ) if self.__save_debug_img: self._save_image( From b60c2cb12911dcd5c9701df21198005950f27216 Mon Sep 17 00:00:00 2001 From: fabienlombard <48451783+fabienlombard@users.noreply.github.com> Date: Sun, 9 Feb 2025 18:18:01 +0100 Subject: [PATCH 3/7] to make the mask remove on the flat image --- .../planktoscope/segmenter/operations.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/processing/segmenter/planktoscope/segmenter/operations.py b/processing/segmenter/planktoscope/segmenter/operations.py index 624e410..5dff51c 100644 --- a/processing/segmenter/planktoscope/segmenter/operations.py +++ b/processing/segmenter/planktoscope/segmenter/operations.py @@ -196,6 +196,32 @@ def remove_previous_mask(mask): __mask_to_remove = mask return __mask_to_remove +def remove_flat_mask(mask): + """Remove the mask from the mask calculated on the flat image + + Args: + mask (cv2 img): mask to apply the operation on + + Returns: + cv2 img: mask after the transformation + """ + global mask_flat + global __mask_to_remove + if __mask_to_remove is not None: + # start = time.monotonic() + # np.append(__mask_to_remove, img_erode_2) + # logger.debug(time.monotonic() - start) + __mask_to_remove = mask_flat + mask_and = mask & __mask_to_remove + mask_final = mask - mask_and + logger.success("Done removing the flat mask") + #__mask_to_remove = mask + return mask_final + else: + logger.debug("First mask") + __mask_to_remove = mask_flat + return __mask_to_remove + def no_op(mask): """Return the mask without modifying it. From af13657900055efda568f61c79994413e37d0a5b Mon Sep 17 00:00:00 2001 From: fabienlombard <48451783+fabienlombard@users.noreply.github.com> Date: Sun, 9 Feb 2025 18:18:13 +0100 Subject: [PATCH 4/7] to make the mask remove on the flat image --- .../segmenter/planktoscope/segmenter/__init__.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/processing/segmenter/planktoscope/segmenter/__init__.py b/processing/segmenter/planktoscope/segmenter/__init__.py index 50d7736..0558c27 100644 --- a/processing/segmenter/planktoscope/segmenter/__init__.py +++ b/processing/segmenter/planktoscope/segmenter/__init__.py @@ -252,7 +252,7 @@ def _create_mask(self, img, debug_saving_path): pipeline = [ # "adaptative_threshold", "simple_threshold", - "remove_previous_mask" if SUBTRACT_CONSECUTIVE_MASKS else "no_op", + "remove_flat_mask" if SUBTRACT_CONSECUTIVE_MASKS else "no_op", "erode", "dilate", "close", @@ -621,6 +621,13 @@ def _pipe(self, ecotaxa_export): ) average_time = 0 + img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) + ret, mask_flat = cv2.threshold( + img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE + ) + self.__mask_to_remove = mask_flat + global mask_flat + # TODO here would be a good place to parallelize the computation for i, filename in enumerate(images_list): @@ -661,6 +668,11 @@ def _pipe(self, ecotaxa_export): f"flat_color_{i}.jpg", ), ) + img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) + ret, mask_flat = cv2.threshold( + img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE + ) + global mask_flat self.__working_debug_path = os.path.join( self.__debug_objects_root, From 93967560c761e7a9531e826ccb53077df48aa178 Mon Sep 17 00:00:00 2001 From: fabienlombard <48451783+fabienlombard@users.noreply.github.com> Date: Sun, 9 Feb 2025 18:56:32 +0100 Subject: [PATCH 5/7] trial to modify my mistakes --- .../planktoscope/segmenter/__init__.py | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/processing/segmenter/planktoscope/segmenter/__init__.py b/processing/segmenter/planktoscope/segmenter/__init__.py index 0558c27..c656d1a 100644 --- a/processing/segmenter/planktoscope/segmenter/__init__.py +++ b/processing/segmenter/planktoscope/segmenter/__init__.py @@ -66,7 +66,7 @@ # Note(ethanjli): if/when we start having more env vars, we may want to start using the `environs` # package from PyPI for more structured parsing of env vars: SUBTRACT_CONSECUTIVE_MASKS = os.getenv( - "SEGMENTER_PIPELINE_SUBTRACT_CONSECUTIVE_MASKS", "True" + "SEGMENTER_PIPELINE_SUBTRACT_CONSECUTIVE_MASKS", "true" ).lower() in ("true", "1", "t") if SUBTRACT_CONSECUTIVE_MASKS: logger.info( @@ -611,8 +611,16 @@ def _pipe(self, ecotaxa_export): self._calculate_flat( images_list[0:images_count], images_count, self.__working_path ) + img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) + ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) + self.__mask_to_remove = mask_flat + global mask_flat else: self._calculate_flat(images_list[0:5], 5, self.__working_path) + img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) + ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) + self.__mask_to_remove = mask_flat + global mask_flat if self.__save_debug_img: self._save_image( @@ -621,12 +629,6 @@ def _pipe(self, ecotaxa_export): ) average_time = 0 - img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) - ret, mask_flat = cv2.threshold( - img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE - ) - self.__mask_to_remove = mask_flat - global mask_flat # TODO here would be a good place to parallelize the computation @@ -649,17 +651,31 @@ def _pipe(self, ecotaxa_export): if len(images_list) <= 5: # there is too few images : take whatever exists flat = self._calculate_flat(images_list, images_count, self.__working_path) + img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) + ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) + self.__mask_to_remove = mask_flat + global mask_flat elif i > (len(images_list) - 6): recalculate_flat = False # We are too close to the end of the list, take the previous 10 images instead of the next 10 flat = self._calculate_flat( images_list[i - 5 : i], 5, self.__working_path ) + flat = self._calculate_flat(images_list, images_count, self.__working_path) + img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) + ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) + self.__mask_to_remove = mask_flat + global mask_flat else: recalculate_flat = False flat = self._calculate_flat( images_list[i : i + 5], 5, self.__working_path ) + flat = self._calculate_flat(images_list, images_count, self.__working_path) + img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) + ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) + self.__mask_to_remove = mask_flat + global mask_flat if self.__save_debug_img: self._save_image( self.__flat, @@ -668,11 +684,7 @@ def _pipe(self, ecotaxa_export): f"flat_color_{i}.jpg", ), ) - img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) - ret, mask_flat = cv2.threshold( - img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE - ) - global mask_flat + self.__working_debug_path = os.path.join( self.__debug_objects_root, From 14fe7c04d4dafd8fa3fc5888e02904c4a0d5ea90 Mon Sep 17 00:00:00 2001 From: fabienlombard <48451783+fabienlombard@users.noreply.github.com> Date: Sun, 9 Feb 2025 19:18:40 +0100 Subject: [PATCH 6/7] trying to clean my mess (second trial) --- .../segmenter/planktoscope/segmenter/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/processing/segmenter/planktoscope/segmenter/__init__.py b/processing/segmenter/planktoscope/segmenter/__init__.py index c656d1a..2b5999e 100644 --- a/processing/segmenter/planktoscope/segmenter/__init__.py +++ b/processing/segmenter/planktoscope/segmenter/__init__.py @@ -614,13 +614,13 @@ def _pipe(self, ecotaxa_export): img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) self.__mask_to_remove = mask_flat - global mask_flat + else: self._calculate_flat(images_list[0:5], 5, self.__working_path) img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) self.__mask_to_remove = mask_flat - global mask_flat + if self.__save_debug_img: self._save_image( @@ -654,7 +654,7 @@ def _pipe(self, ecotaxa_export): img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) self.__mask_to_remove = mask_flat - global mask_flat + elif i > (len(images_list) - 6): recalculate_flat = False # We are too close to the end of the list, take the previous 10 images instead of the next 10 @@ -665,7 +665,7 @@ def _pipe(self, ecotaxa_export): img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) self.__mask_to_remove = mask_flat - global mask_flat + else: recalculate_flat = False flat = self._calculate_flat( @@ -675,7 +675,7 @@ def _pipe(self, ecotaxa_export): img_gray_flat = cv2.cvtColor(self.__flat, cv2.COLOR_BGR2GRAY) ret, mask_flat = cv2.threshold(img_gray_flat, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_TRIANGLE) self.__mask_to_remove = mask_flat - global mask_flat + if self.__save_debug_img: self._save_image( self.__flat, From 103fcfc0fb19fa99224cb7eb21dc0c47826b2968 Mon Sep 17 00:00:00 2001 From: fabienlombard <48451783+fabienlombard@users.noreply.github.com> Date: Sun, 9 Feb 2025 19:20:58 +0100 Subject: [PATCH 7/7] trying to clean my mess (second trial) --- processing/segmenter/planktoscope/segmenter/operations.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/processing/segmenter/planktoscope/segmenter/operations.py b/processing/segmenter/planktoscope/segmenter/operations.py index 5dff51c..71217e6 100644 --- a/processing/segmenter/planktoscope/segmenter/operations.py +++ b/processing/segmenter/planktoscope/segmenter/operations.py @@ -205,22 +205,16 @@ def remove_flat_mask(mask): Returns: cv2 img: mask after the transformation """ - global mask_flat global __mask_to_remove if __mask_to_remove is not None: # start = time.monotonic() # np.append(__mask_to_remove, img_erode_2) # logger.debug(time.monotonic() - start) - __mask_to_remove = mask_flat mask_and = mask & __mask_to_remove mask_final = mask - mask_and logger.success("Done removing the flat mask") - #__mask_to_remove = mask return mask_final - else: - logger.debug("First mask") - __mask_to_remove = mask_flat - return __mask_to_remove + def no_op(mask):