class_docstr: This is the object detection class for using your custom trained models. 
  It supports your custom trained YOLOv3 and TinyYOLOv3 model and allows 
  to you to perform object detection in images.
docstr: Detects objects in an image using the unique classes provided
  by COCO.
  
  :param input_image: path to an image file, cv2 image or PIL image
  :param output_image_path: path to save input image with predictions rendered
  :param output_type: type of output for rendered image. Acceptable values are 'file' and 'array` ( a cv2 image )
  :param extract_detected_objects: extract each object based on the output type
  :param minimum_percentage_probability: the minimum confidence a detected object must have
  :param display_percentage_probability: to diplay/not display the confidence on rendered image   
  :param display_object_name: to diplay/not display the object name on rendered image  
  :param display_box: to diplay/not display the object bounding box on rendered image 
  :param custom_objects: a dictionary of detectable objects set to boolean values
  
  :returns: A list of tuples containing the label of detected object and the
  confidence.
docstr_tok: ["Detects","objects","in","an","image","using","the","unique","classes","provided","by","COCO",".",":","param","input_image",":","path","to","an","image","file",",","cv2","image","or","PIL","image",":","param","output_image_path",":","path","to","save","input","image","with","predictions","rendered",":","param","output_type",":","type","of","output","for","rendered","image",".","Acceptable","values","are","'file","'","and","'array","`","(","a","cv2","image",")",":","param","extract_detected_objects",":","extract","each","object","based","on","the","output","type",":","param","minimum_percentage_probability",":","the","minimum","confidence","a","detected","object","must","have",":","param","display_percentage_probability",":","to","diplay\/not","display","the","confidence","on","rendered","image",":","param","display_object_name",":","to","diplay\/not","display","the","object","name","on","rendered","image",":","param","display_box",":","to","diplay\/not","display","the","object","bounding","box","on","rendered","image",":","param","custom_objects",":","a","dictionary","of","detectable","objects","set","to","boolean","values",":","returns",":","A","list","of","tuples","containing","the","label","of","detected","object","and","the","confidence","."]
code: def detectObjectsFromImage(
      self,
      input_image: Union[str, np.ndarray, Image.Image],
      output_image_path: str = None,
      output_type: str = "file",
      extract_detected_objects: bool = False,
      minimum_percentage_probability: int = 40,
      display_percentage_probability: bool = True,
      display_object_name: bool = True,
      display_box: bool = True,
      custom_objects: List = None,
      nms_treshold: float = 0.4,
      objectness_treshold: float = 0.4,
  ) -> Union[
      List[List[Tuple[str, float, Dict[str, int]]]],
      np.ndarray,
      List[np.ndarray],
      List[str],
  ]:
      """
      Detects objects in an image using the unique classes provided
      by COCO.
  
      :param input_image: path to an image file, cv2 image or PIL image
      :param output_image_path: path to save input image with predictions rendered
      :param output_type: type of output for rendered image. Acceptable values are 'file' and 'array` ( a cv2 image )
      :param extract_detected_objects: extract each object based on the output type
      :param minimum_percentage_probability: the minimum confidence a detected object must have
      :param display_percentage_probability: to diplay/not display the confidence on rendered image
      :param display_object_name: to diplay/not display the object name on rendered image
      :param display_box: to diplay/not display the object bounding box on rendered image
      :param custom_objects: a dictionary of detectable objects set to boolean values
  
      :returns: A list of tuples containing the label of detected object and the
      confidence.
      """
  
      self.__nms_score = nms_treshold
      self.__objectness_score = objectness_treshold
  
      self.__model.eval()
      if not self.__model_loaded:
          if self.__model_path:
              warnings.warn(
                  "Model path has changed but pretrained weights in the"
                  " new path is yet to be loaded.",
                  ResourceWarning,
              )
          else:
              raise RuntimeError(
                  "Model path isn't set, pretrained weights aren't used."
              )
  
      predictions = defaultdict(lambda: [])
  
      if (
          self.__model_type == "yolov3"
          or self.__model_type == "tiny-yolov3"
      ):
          (
              fnames,
              original_imgs,
              input_dims,
              imgs,
          ) = self.__load_image_yolo(input_image)
  
          with torch.no_grad():
              output = self.__model(imgs)
  
          output = get_predictions(
              pred=output.to(self.__device),
              num_classes=len(self.__classes),
              nms_confidence_level=self.__nms_score,
              objectness_confidence=self.__objectness_score,
              device=self.__device,
          )
  
          if output is None:
              if output_type == "array":
                  if extract_detected_objects:
                      return original_imgs[0], [], []
                  else:
                      return original_imgs[0], []
              else:
                  if extract_detected_objects:
                      return original_imgs[0], []
                  else:
                      return []
  
          # scale the output to match the dimension of the original image
          input_dims = torch.index_select(
              input_dims, 0, output[:, 0].long()
          )
          scaling_factor = torch.min(416 / input_dims, 1)[0].view(-1, 1)
          output[:, [1, 3]] -= (
              416 - (scaling_factor * input_dims[:, 0].view(-1, 1))
          ) / 2
          output[:, [2, 4]] -= (
              416 - (scaling_factor * input_dims[:, 1].view(-1, 1))
          ) / 2
          output[:, 1:5] /= scaling_factor
  
          # clip bounding box for those that extended outside the detected image.
          for idx in range(output.shape[0]):
              output[idx, [1, 3]] = torch.clamp(
                  output[idx, [1, 3]], 0.0, input_dims[idx, 0]
              )
              output[idx, [2, 4]] = torch.clamp(
                  output[idx, [2, 4]], 0.0, input_dims[idx, 1]
              )
  
          for pred in output:
              pred_label = self.__classes[int(pred[-1])]
              if custom_objects:
                  if (
                      pred_label.replace(" ", "_")
                      in custom_objects.keys()
                  ):
                      if not custom_objects[
                          pred_label.replace(" ", "_")
                      ]:
                          continue
                  else:
                      continue
              predictions[int(pred[0])].append(
                  (
                      pred_label,
                      float(pred[-2]),
                      {
                          k: v
                          for k, v in zip(
                              ["x1", "y1", "x2", "y2"],
                              map(int, pred[1:5]),
                          )
                      },
                  )
              )
  
      # Render detection on copy of input image
      original_input_image = None
      output_image_array = None
      extracted_objects = []
  
      if (
          self.__model_type == "yolov3"
          or self.__model_type == "tiny-yolov3"
      ):
          original_input_image = cv2.cvtColor(
              original_imgs[0], cv2.COLOR_RGB2BGR
          )
          if isinstance(output, torch.Tensor):
              for pred in output:
                  percentage_conf = round(float(pred[-2]) * 100, 2)
                  if percentage_conf < minimum_percentage_probability:
                      continue
  
                  displayed_label = ""
                  if display_object_name:
                      displayed_label = (
                          f"{self.__classes[int(pred[-1].item())]} : "
                      )
                  if display_percentage_probability:
                      displayed_label += f" {percentage_conf}%"
  
                  original_imgs[
                      int(pred[0].item())
                  ] = draw_bbox_and_label(
                      pred[1:5].int() if display_box else None,
                      displayed_label,
                      original_imgs[int(pred[0].item())],
                  )
              output_image_array = cv2.cvtColor(
                  original_imgs[0], cv2.COLOR_RGB2BGR
              )
  
      # Format predictions for function reponse
      predictions_batch = list(predictions.values())
      predictions_list = (
          predictions_batch[0] if len(predictions_batch) > 0 else []
      )
      min_probability = minimum_percentage_probability / 100
  
      if output_type == "file":
          if output_image_path:
              cv2.imwrite(output_image_path, output_image_array)
  
              if extract_detected_objects:
                  extraction_dir = (
                      ".".join(output_image_path.split(".")[:-1])
                      + "-extracted"
                  )
                  os.mkdir(extraction_dir)
                  count = 0
                  for obj_prediction in predictions_list:
                      if obj_prediction[1] >= min_probability:
                          count += 1
                          extracted_path = os.path.join(
                              extraction_dir,
                              ".".join(
                                  os.path.basename(
                                      output_image_path
                                  ).split(".")[:-1]
                              )
                              + f"-{count}.jpg",
                          )
                          obj_bbox = obj_prediction[2]
                          cv2.imwrite(
                              extracted_path,
                              original_input_image[
                                  obj_bbox["y1"] : obj_bbox["y2"],
                                  obj_bbox["x1"] : obj_bbox["x2"],
                              ],
                          )
  
                          extracted_objects.append(extracted_path)
  
      elif output_type == "array":
          if extract_detected_objects:
              for obj_prediction in predictions_list:
                  if obj_prediction[1] >= min_probability:
                      obj_bbox = obj_prediction[2]
  
                      extracted_objects.append(
                          original_input_image[
                              obj_bbox["y1"] : obj_bbox["y2"],
                              obj_bbox["x1"] : obj_bbox["x2"],
                          ]
                      )
      else:
          raise ValueError(
              f"Invalid output_type '{output_type}'. Supported values are 'file' and 'array' "
          )
  
      predictions_list = [
          {
              "name": prediction[0],
              "percentage_probability": round(prediction[1] * 100, 2),
              "box_points": [
                  prediction[2]["x1"],
                  prediction[2]["y1"],
                  prediction[2]["x2"],
                  prediction[2]["y2"],
              ],
          }
          for prediction in predictions_list
          if prediction[1] >= min_probability
      ]
  
      if output_type == "array":
          if extract_detected_objects:
              return (
                  output_image_array,
                  predictions_list,
                  extracted_objects,
              )
          else:
              return output_image_array, predictions_list
      else:
          if extract_detected_objects:
              return predictions_list, extracted_objects
          else:
              return predictions_list
  
imports: import os
  import time
  import math
  import json
  import warnings
  from typing import List, Union, Tuple, Dict
  from collections import defaultdict
  import numpy
  from PIL import Image
  import cv2
  import torch
  from torch.cuda import amp
  from torch.utils.data import DataLoader
  from torch.optim import SGD, lr_scheduler
  from tqdm import tqdm
  from .yolo.dataset import LoadImagesAndLabels
  from .yolo.custom_anchors import generate_anchors
  from .yolo.compute_loss import compute_loss
  from .yolo import validate
  from ...yolov3.tiny_yolov3 import YoloV3Tiny
  from ...yolov3.yolov3 import YoloV3
  from ...yolov3.utils import draw_bbox_and_label, get_predictions, prepare_image
  from ...backend_check.model_extension import extension_check
label_desc: Use image node_id 10 for calling the CustomObjectDetection obj's underlying member method code with example usage: obj.detectObjectsFromImage(input_image, output_image_path, output_type, extract_detected_objects, minimum_percentage_probability, display_percentage_probability, display_object_name, display_box, custom_objects, nms_treshold, objectness_treshold) and returns: output_image_array,  predictions_list,  extracted_objects, output_image_array,  predictions_list, predictions_list,  extracted_objects, predictions_list, original_imgs,  list,  list, original_imgs,  list, original_imgs,  list, list