Source code for geographer.label_makers.seg_label_maker_base
"""Base class for segmentation label makers."""from__future__importannotationsimportloggingfromabcimportabstractmethodfrompydanticimportBaseModel,Fieldfromtqdm.autoimporttqdmfromgeographer.base_model_dict_conversion.save_load_base_model_mixinimport(SaveAndLoadBaseModelMixIn,)fromgeographer.connectorimportConnectorfromgeographer.label_makers.label_maker_baseimportLabelMaker# loggerlog=logging.getLogger(__name__)
[docs]classSegLabelMaker(LabelMaker,BaseModel,SaveAndLoadBaseModelMixIn):"""Base class for segmentation label makers."""add_background_band:bool=Field(default=True,description="Whether to add implicit background band.")@abstractmethoddef_make_label_for_raster(self,connector:Connector,raster_name:str):"""Make label for single raster."""pass@property@abstractmethoddeflabel_type(self)->str:"""Return label type."""passdef_after_make_labels(self,connector:Connector):"""Run after making labels. Override this hook in subclass to apply custom logic after making labels. """passdef_run_safety_checks(self,connector:Connector):"""Run safety checks. Hook. Override to check e.g. if existing classes in vectors contained in connector.all_vector_classes. """pass
[docs]defmake_labels(self,connector:Connector,raster_names:list[str]|None=None,):"""Create segmentation labels. Args: raster_names: list of raster names to create labels for. Defaults to None (i.e. all rasters without a label). """# safety checksself._run_safety_checks(connector)self._set_label_type_in_connector_attrs(connector)self._compare_existing_rasters_to_rasters(connector)connector.labels_dir.mkdir(parents=True,exist_ok=True)existing_rasters={raster_path.nameforraster_pathinconnector.rasters_dir.iterdir()ifraster_path.is_file()andraster_path.nameinconnector.rasters.index}ifraster_namesisNone:# Find rasters without labelsexisting_labels={raster_path.nameforraster_pathinconnector.labels_dir.iterdir()ifraster_path.is_file()andraster_path.nameinconnector.rasters.index}raster_names=existing_rasters-existing_labelselifnotset(raster_names)<=existing_rasters:raiseFileNotFoundError("Can't make labels for missing rasters: "f"{existing_rasters-raster_names}")forraster_nameintqdm(raster_names,desc="Making labels: "):self._make_label_for_raster(connector=connector,raster_name=raster_name)connector.attrs["label_type"]=self.label_typeself._after_make_labels(connector)connector.save()
[docs]defdelete_labels(self,connector:Connector,raster_names:list[str]|None=None,):"""Delete (pixel) labels from the connector's labels_dir. Args: raster_names: names of rasters for which to delete labels. Defaults to None, i.e. all labels. """ifraster_namesisNone:raster_names=connector.rasters.indexforraster_nameintqdm(raster_names,desc="Deleting labels: "):(connector.labels_dir/raster_name).unlink(missing_ok=True)
def_set_label_type_in_connector_attrs(self,connector:Connector):connector.attrs["label_type"]=self.label_type@staticmethoddef_compare_existing_rasters_to_rasters(connector:Connector):"""Safety check. Compare sets of rasters in rasters_dir and in connector.rasters. Raises warnings if there is a discrepancy. """# Find the set of existing rasters in the dataset, ...existing_rasters={raster_path.nameforraster_pathinconnector.rasters_dir.iterdir()ifraster_path.is_file()}# ... then if the set of rasters is a strict subset# of the rasters in rasters ...ifexisting_rasters<set(connector.rasters.index):# ... log a warninglog.warning("There are rasters in connector.rasters that ""are not in the rasters_dir %s.",connector.rasters_dir,)# ... and if it is not a subset, ...ifnotexisting_rasters<=set(connector.rasters.index):# ... log an warningmessage=("Warning! There are rasters in the dataset's rasters ""subdirectory that are not in connector.rasters.")log.warning(message)