Retinal ganglion cell (RGC) quantifier

Author

Renee Ti Chou and Henry T. Hsueh

Published

2023-05-03

Note

This is an archived notebook of the cell counting program developed using Faster R-CNN with Inception Resnet v2 object detection model for the paper “Engineered peptide-drug conjugate provides sustained protection of retinal ganglion cells with topical administration in rats.” The model framework was obtained from the TensorFlow Model Garden (Hongkun Yu and Li 2020).

Select model

Code
MODEL_NAME = 'Rat40XFasterRCNN' #@param ['Rat40XFasterRCNN']

Mount Google drive

Code
from google.colab import drive
drive.mount('/content/gdrive', force_remount=True)
%cd /content/gdrive/My Drive/RGC_quantifier_DoNotTouch_Copy

Tensorflow setup

Code
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior
Code
!pip install progressbar2
import os
import pathlib
if "models" in pathlib.Path.cwd().parts:
  while "models" in pathlib.Path.cwd().parts:
    os.chdir('..')
elif not pathlib.Path('models').exists():
  !git clone --depth 1 https://github.com/tensorflow/models
%cd models/research/
!protoc object_detection/protos/*.proto --python_out=.
!pip install .
%cd /content/gdrive/My Drive/RGC_quantifier_DoNotTouch_Copy

Object detection setup

Code
!pip install tf_slim
Code
import pandas as pd
import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
# import tensorflow as tf
import zipfile

from distutils.version import StrictVersion
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image

from object_detection.utils import ops as utils_ops
from object_detection.utils import label_map_util
from object_detection.utils import visualization_utils as vis_util
import progressbar
from datetime import datetime

MODEL_PATH = 'source_code/' + MODEL_NAME + '_inference_graph/frozen_inference_graph.pb'
LABEL_PATH = 'source_code/' + MODEL_NAME + '_inference_graph/object-detection.pbtxt'
IMAGE_DIR = 'RGC_images'
RESULT_DIR = 'results'
NUM_CLASSES = 1

JPG_IMGS = os.listdir(IMAGE_DIR)
IMAGE_PATHS = [os.path.join(IMAGE_DIR, img) for img in JPG_IMGS if img.endswith('.jpg')]
IMAGE_SIZE = (12, 8) # size of output images
COUNTING_RES = list()

# functions
def load_image_into_numpy_array(image):
  (im_width, im_height) = image.size
  return np.array(image.getdata()).reshape(
      (im_height, im_width, 3)).astype(np.uint8)

def run_inference_for_single_image(image, graph):
  with graph.as_default():
    with tf.Session() as sess:
      # Get handles to input and output tensors
      ops = tf.get_default_graph().get_operations()
      all_tensor_names = {output.name for op in ops for output in op.outputs}
      tensor_dict = {}
      for key in [
          'num_detections', 'detection_boxes', 'detection_scores',
          'detection_classes', 'detection_masks'
      ]:
        tensor_name = key + ':0'
        if tensor_name in all_tensor_names:
          tensor_dict[key] = tf.get_default_graph().get_tensor_by_name(
              tensor_name)
      if 'detection_masks' in tensor_dict:
        # The following processing is only for single image
        detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0])
        detection_masks = tf.squeeze(tensor_dict['detection_masks'], [0])
        # Reframe is required to translate mask from box coordinates to image coordinates and fit the image size.
        real_num_detection = tf.cast(tensor_dict['num_detections'][0], tf.int32)
        detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1])
        detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1])
        detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(
            detection_masks, detection_boxes, image.shape[0], image.shape[1])
        detection_masks_reframed = tf.cast(
            tf.greater(detection_masks_reframed, 0.5), tf.uint8)
        # Follow the convention by adding back the batch dimension
        tensor_dict['detection_masks'] = tf.expand_dims(
            detection_masks_reframed, 0)
      image_tensor = tf.get_default_graph().get_tensor_by_name('image_tensor:0')

      # Run inference
      output_dict = sess.run(tensor_dict,
                             feed_dict={image_tensor: np.expand_dims(image, 0)})

      # all outputs are float32 numpy arrays, so convert types as appropriate
      output_dict['num_detections'] = int(output_dict['num_detections'][0])
      output_dict['detection_classes'] = output_dict[
          'detection_classes'][0].astype(np.uint8)
      output_dict['detection_boxes'] = output_dict['detection_boxes'][0]
      output_dict['detection_scores'] = output_dict['detection_scores'][0]
      if 'detection_masks' in output_dict:
        output_dict['detection_masks'] = output_dict['detection_masks'][0]
  return output_dict

def detect_objects(image_path):
  image = Image.open(image_path)
  # the array based representation of the image will be used later in order to prepare the
  # result image with boxes and labels on it.
  image_np = load_image_into_numpy_array(image)
  # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
  image_np_expanded = np.expand_dims(image_np, axis=0)
  # Actual detection.
  output_dict = run_inference_for_single_image(image_np, detection_graph)
  # Visualization of the results of a detection.
  vis_util.visualize_boxes_and_labels_on_image_array(
      image_np,
      output_dict['detection_boxes'],
      output_dict['detection_classes'],
      output_dict['detection_scores'],
      category_index,
      instance_masks=output_dict.get('detection_masks'),
      use_normalized_coordinates=True,
      line_thickness=8,
      max_boxes_to_draw=None)
  # Plot the image result
  plt.figure(figsize=IMAGE_SIZE)
  plt.imshow(image_np)
  plt.savefig(os.path.join(RESULT_DIR, image_path.split('/')[1]))
  COUNTING_RES.append({'file_name': image_path.split('/')[1], 'counts': sum(output_dict['detection_scores'] > 0.5)})

# load frozen model
detection_graph = tf.Graph()
with detection_graph.as_default():
  od_graph_def = tf.GraphDef()
  with tf.gfile.GFile(MODEL_PATH, 'rb') as fid:
    serialized_graph = fid.read()
    od_graph_def.ParseFromString(serialized_graph)
    tf.import_graph_def(od_graph_def, name='')

# load label map
category_index = label_map_util.create_category_index_from_labelmap(LABEL_PATH, use_display_name=True)

Run object detection

Code
for i in progressbar.progressbar(range(0, len(IMAGE_PATHS))): # detect objects
    detect_objects(IMAGE_PATHS[i])
pd.DataFrame(COUNTING_RES).to_csv(RESULT_DIR + '/counting_result.tsv', sep='\t', index=False) # output counting result
print('DONE! (' + datetime.now().strftime("%m/%d/%Y") + '; model: ' + MODEL_NAME + ')')

References

Hongkun Yu, Xianzhi Du, Chen Chen, and Jing Li. 2020. TensorFlow Model Garden.” https://github.com/tensorflow/models.

Creative Commons License
The notebook is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.