code: ######## Image Object Detection Using Tensorflow-trained Classifier #########
  #
  # Author: Evan Juras
  # Date: 1/15/18
  # Description: 
  # This program uses a TensorFlow-trained neural network to perform object detection.
  # It loads the classifier and uses it to perform object detection on an image.
  # It draws boxes, scores, and labels around the objects of interest in the image.
  
  ## Some of the code is copied from Google's example at
  ## https://github.com/tensorflow/models/blob/master/research/object_detection/object_detection_tutorial.ipynb
  
  ## and some is copied from Dat Tran's example at
  ## https://github.com/datitran/object_detector_app/blob/master/object_detection_app.py
  
  ## but I changed it to make it more understandable to me.
  
  # Import packages
  import os
  #os.environ['CUDA_DEVICE_ORDER'] = 'PCI_BUS_ID'
  #os.environ['CUDA_VISIBLE_DEVICES'] = '1'
  os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'  # or any {'0', '1', '2'} to supress warnings
  import cv2
  import numpy as np
  import tensorflow as tf
  tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
  import logging
  logging.getLogger('tensorflow').setLevel(logging.FATAL)
  import sys
  import time
  
  # This is needed since the notebook is stored in the object_detection folder.
  sys.path.append("..")
  
  # Import utilites
  from utils import label_map_util
  from utils import visualization_utils as vis_util
  
  # Name of the directory containing the object detection module we're using
  MODEL_NAME = 'inference_graph'
  IMAGE_NAME = 'test_orig.jpg'
  IMAGE_RESULT_NAME = 'test_result.jpg'
  
  # Grab path to current working directory
  CWD_PATH = os.getcwd()
  
  # patch tf1 into `utils.ops`
  #utils_ops.tf = tf.compat.v1
  
  # Patch the location of gfile
  tf.gfile = tf.io.gfile
  
  # Path to frozen detection graph .pb file, which contains the model that is used
  # for object detection.
  PATH_TO_CKPT = os.path.join(CWD_PATH,MODEL_NAME,'frozen_inference_graph.pb')
  
  # Path to label map file
  PATH_TO_LABELS = os.path.join(CWD_PATH,'training','labelmap.pbtxt')
  
  # Path to image
  #PATH_TO_IMAGE = os.path.join(CWD_PATH,IMAGE_NAME)
  
  # Number of classes the object detector can identify
  NUM_CLASSES = 90
  
  # Load the label map.
  # Label maps map indices to category names, so that when our convolution
  # network predicts `5`, we know that this corresponds to `king`.
  # Here we use internal utility functions, but anything that returns a
  # dictionary mapping integers to appropriate string labels would be fine
  label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
  categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
  category_index = label_map_util.create_category_index(categories)
  
  # Load the Tensorflow model into memory.
  detection_graph = tf.Graph()
  with detection_graph.as_default():
      od_graph_def = tf.compat.v1.GraphDef()
      with tf.io.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
          serialized_graph = fid.read()
          od_graph_def.ParseFromString(serialized_graph)
          tf.import_graph_def(od_graph_def, name='')
  
      # CPU only
      #sess = tf.compat.v1.Session(graph=detection_graph)
  
      # GPU options to avoid GPU out-of-memory crash
      #gpu_options = tf.compat.v1.GPUOptions(per_process_gpu_memory_fraction=0.5) 
      #gpu_options = tf.GPUOptions(allow_growth = True)
      # for tf2
      gpu_options = tf.compat.v1.GPUOptions(allow_growth = True)
      sess = tf.compat.v1.Session(graph=detection_graph,config=tf.compat.v1.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
  
  # Define input and output tensors (i.e. data) for the object detection classifier
  
  # Input tensor is the image
  image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
  
  # Output tensors are the detection boxes, scores, and classes
  # Each box represents a part of the image where a particular object was detected
  detection_boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
  
  # Each score represents level of confidence for each of the objects.
  # The score is shown on the result image, together with the class label.
  detection_scores = detection_graph.get_tensor_by_name('detection_scores:0')
  detection_classes = detection_graph.get_tensor_by_name('detection_classes:0')
  
  # Number of objects detected
  num_detections = detection_graph.get_tensor_by_name('num_detections:0')
  
  start = time.time()
  # Load image using OpenCV and
  # expand image dimensions to have shape: [1, None, None, 3]
  # i.e. a single-column array, where each item in the column has the pixel RGB value
  PATH_TO_IMAGE = os.path.join(CWD_PATH,IMAGE_NAME)
  print("Detecting objects in file:", PATH_TO_IMAGE)
  image = cv2.imread(PATH_TO_IMAGE)
  image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  image_expanded = np.expand_dims(image_rgb, axis=0)
  
  # Perform the actual detection by running the model with the image as input
  (boxes, scores, classes, num) = sess.run(
    [detection_boxes, detection_scores, detection_classes, num_detections],
    feed_dict={image_tensor: image_expanded})
  
  # Draw the results of the detection (aka 'visulaize the results')
  
  vis_util.visualize_boxes_and_labels_on_image_array(
    image,
    np.squeeze(boxes),
    np.squeeze(classes).astype(np.int32),
    np.squeeze(scores),
    category_index,
    use_normalized_coordinates=True,
    line_thickness=4,
    min_score_thresh=0.50)
  
  end = time.time()
  print(end - start)
  # All the results have been drawn on image. Now display the image.
  #cv2.imshow('Object detector', image)
  cv2.imwrite(IMAGE_RESULT_NAME, image)
  print("Saving result image to: ", IMAGE_RESULT_NAME)
  
  # Clean up
  cv2.destroyAllWindows()
  
apis: tensorflow.compat.v1.GPUOptions numpy.squeeze tensorflow.io.gfile.GFile tensorflow.compat.v1.ConfigProto tensorflow.Graph numpy.expand_dims tensorflow.compat.v1.GraphDef tensorflow.import_graph_def tensorflow.compat.v1.logging.set_verbosity