import os, shutil, random from PIL import Image from ultralytics import YOLO from ultralytics.utils.plotting import Annotator class SaigonBeer_Recognition: def __init__(self, cfg): self.cfg = cfg self.classifier = YOLO(self.cfg["Model"]['classifier']) self.detector = YOLO(self.cfg["Model"]['detector']) self.color = {#"others": (255,0,0), "saigon_export":(0,255,0), "saigon_chill":(0,0,255), "saigon_large":(255,255,0), "saigon_special":(255,0,255), "saigon_gold":(255,0,0)} def forward(self, img, save_path=None): detected_objs = self.detector.predict(img) object_info = self.get_objects(detected_objs) object_info = self.box_filtering(object_info) # dictionary result = {} annotated_image = img.copy() for key, value in object_info.items(): cropped_img = self.image_cropping(img, value['bbox']) kind = value['label'] beer = self.classifier.predict(source=cropped_img, conf=0.5) beer = self.got_final_result(beer) result[key] = {"shape": kind, "beer": beer} if beer == "others": continue annotated_image = self.draw_img(annotated_image, value['bbox'], kind, beer, color=self.color[beer]) return result, annotated_image def got_final_result(self, results): ''' Get the label of the largest probability. Args: results: The results of the prediction. Returns: The label of the largest probability. ''' id2label = results[0].names for result in results: cls = result.probs.top1 return id2label[cls] def image_cropping(self, img, bbox): ''' Crop the image based on the bounding box. Args: img: The path of the image. bbox: The bounding box of the object. Returns: The cropped image. ''' x_min, y_min, x_max, y_max = bbox cropped_img = img.crop((x_min, y_min, x_max, y_max)) return cropped_img def get_objects(self, predictions): ''' Get the information of detected object. Args: predictions: The results of the prediction. Returns: A dictionary containing the information of detected object. ''' object_dict = {} for i, prediction in enumerate(predictions): boxes = prediction.boxes for j, box in enumerate(boxes): object_key = f"object_{i}_{j}" object_dict[object_key] = { 'label': prediction.names[int(box.cls)], 'bbox': box.xyxy.tolist()[0], 'prob': box.conf.tolist()[0] } return object_dict def box_filtering(self, predictions): ''' Filtering out the lowest boxes Args: predictions: The results of the prediction. Returns: The filtered predictions. ''' # Create a copy of the keys to iterate over keys_to_remove = [] for key, value in predictions.items(): if value['prob'] < 0.5: keys_to_remove.append(key) # Remove keys outside of the loop for key in keys_to_remove: del predictions[key] return predictions def draw_img(self, img, bbox, shape, beer, color=(0,255,0)): self.annotator = Annotator(img) self.annotator.box_label(bbox, f"{beer} {shape}", color=color) annotated_image = self.annotator.result() # Convert the NumPy array to a PIL Image before saving annotated_image = Image.fromarray(annotated_image) return annotated_image