diff --git a/processing/segmenter/planktoscope/segmenter/__init__.py b/processing/segmenter/planktoscope/segmenter/__init__.py index d9641f0..2b5999e 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( @@ -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", @@ -599,18 +599,28 @@ 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: - recalculate_flat = False + 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 ) + 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 + else: - self._calculate_flat(images_list[0:10], 10, self.__working_path) + 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 + if self.__save_debug_img: self._save_image( @@ -620,6 +630,7 @@ def _pipe(self, ecotaxa_export): average_time = 0 + # TODO here would be a good place to parallelize the computation for i, filename in enumerate(images_list): name = os.path.splitext(filename)[0] @@ -629,22 +640,42 @@ 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) - 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 - flat = self._calculate_flat(images_list, 10, self.__working_path) - elif i > (len(images_list) - 11): + if recalculate_flat: # not i % 5 and i < (images_count - 5) + + 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 + + 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 ) + 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 + 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 ) + 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 + if self.__save_debug_img: self._save_image( self.__flat, @@ -654,6 +685,7 @@ def _pipe(self, ecotaxa_export): ), ) + self.__working_debug_path = os.path.join( self.__debug_objects_root, self.__working_path.split(self.__img_path)[1].strip(), diff --git a/processing/segmenter/planktoscope/segmenter/operations.py b/processing/segmenter/planktoscope/segmenter/operations.py index 624e410..71217e6 100644 --- a/processing/segmenter/planktoscope/segmenter/operations.py +++ b/processing/segmenter/planktoscope/segmenter/operations.py @@ -196,6 +196,26 @@ 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_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_and = mask & __mask_to_remove + mask_final = mask - mask_and + logger.success("Done removing the flat mask") + return mask_final + + def no_op(mask): """Return the mask without modifying it.