Source code for anomalib.post_processing.post_process
"""Post Process This module contains utils function to apply post-processing to the output predictions."""# Copyright (C) 2022 Intel Corporation# SPDX-License-Identifier: Apache-2.0importmathfromtypingimportOptional,Tupleimportcv2importnumpyasnpfromskimageimportmorphology
[docs]defadd_label(image:np.ndarray,label_name:str,color:Tuple[int,int,int],confidence:Optional[float]=None,font_scale:float=5e-3,thickness_scale=1e-3,):"""Adds a label to an image. Args: image (np.ndarray): Input image. label_name (str): Name of the label that will be displayed on the image. color (Tuple[int, int, int]): RGB values for background color of label. confidence (Optional[float]): confidence score of the label. font_scale (float): scale of the font size relative to image size. Increase for bigger font. thickness_scale (float): scale of the font thickness. Increase for thicker font. Returns: np.ndarray: Image with label. """image=image.copy()img_height,img_width,_=image.shapefont=cv2.FONT_HERSHEY_PLAINtext=label_nameifconfidenceisNoneelsef"{label_name} ({confidence*100:.0f}%)"# get font sizingfont_scale=min(img_width,img_height)*font_scalethickness=math.ceil(min(img_width,img_height)*thickness_scale)(width,height),baseline=cv2.getTextSize(text,font,fontScale=font_scale,thickness=thickness)# create labellabel_patch=np.zeros((height+baseline,width+baseline,3),dtype=np.uint8)label_patch[:,:]=colorcv2.putText(label_patch,text,(0,baseline//2+height),font,fontScale=font_scale,thickness=thickness,color=0,lineType=cv2.LINE_AA,)# add label to imageimage[:baseline+height,:baseline+width]=label_patchreturnimage
[docs]defadd_normal_label(image:np.ndarray,confidence:Optional[float]=None):"""Adds the normal label to the image."""returnadd_label(image,"normal",(225,252,134),confidence)
[docs]defadd_anomalous_label(image:np.ndarray,confidence:Optional[float]=None):"""Adds the anomalous label to the image."""returnadd_label(image,"anomalous",(255,100,100),confidence)
[docs]defanomaly_map_to_color_map(anomaly_map:np.ndarray,normalize:bool=True)->np.ndarray:"""Compute anomaly color heatmap. Args: anomaly_map (np.ndarray): Final anomaly map computed by the distance metric. normalize (bool, optional): Bool to normalize the anomaly map prior to applying the color map. Defaults to True. Returns: np.ndarray: [description] """ifnormalize:anomaly_map=(anomaly_map-anomaly_map.min())/np.ptp(anomaly_map)anomaly_map=anomaly_map*255anomaly_map=anomaly_map.astype(np.uint8)anomaly_map=cv2.applyColorMap(anomaly_map,cv2.COLORMAP_JET)anomaly_map=cv2.cvtColor(anomaly_map,cv2.COLOR_BGR2RGB)returnanomaly_map
[docs]defsuperimpose_anomaly_map(anomaly_map:np.ndarray,image:np.ndarray,alpha:float=0.4,gamma:int=0,normalize:bool=False)->np.ndarray:"""Superimpose anomaly map on top of in the input image. Args: anomaly_map (np.ndarray): Anomaly map image (np.ndarray): Input image alpha (float, optional): Weight to overlay anomaly map on the input image. Defaults to 0.4. gamma (int, optional): Value to add to the blended image to smooth the processing. Defaults to 0. Overall, the formula to compute the blended image is I' = (alpha*I1 + (1-alpha)*I2) + gamma normalize: whether or not the anomaly maps should be normalized to image min-max Returns: np.ndarray: Image with anomaly map superimposed on top of it. """anomaly_map=anomaly_map_to_color_map(anomaly_map.squeeze(),normalize=normalize)superimposed_map=cv2.addWeighted(anomaly_map,alpha,image,(1-alpha),gamma)returnsuperimposed_map
[docs]defcompute_mask(anomaly_map:np.ndarray,threshold:float,kernel_size:int=4)->np.ndarray:"""Compute anomaly mask via thresholding the predicted anomaly map. Args: anomaly_map (np.ndarray): Anomaly map predicted via the model threshold (float): Value to threshold anomaly scores into 0-1 range. kernel_size (int): Value to apply morphological operations to the predicted mask. Defaults to 4. Returns: Predicted anomaly mask """anomaly_map=anomaly_map.squeeze()mask:np.ndarray=np.zeros_like(anomaly_map).astype(np.uint8)mask[anomaly_map>threshold]=1kernel=morphology.disk(kernel_size)mask=morphology.opening(mask,kernel)mask*=255returnmask