text: # --------------------------------------------------------
  # Tensorflow Faster R-CNN
  # Licensed under The MIT License [see LICENSE for details]
  # Written by Xinlei Chen
  # --------------------------------------------------------
  from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  from lib.nets.vgg16 import vgg16
  from lib.datasets.factory import get_imdb
  from lib.datasets.imdb import imdb as imdb2
  from lib.datasets import roidb as rdl_roidb
  from lib.layer_utils.roi_data_layer import RoIDataLayer
  import tensorflow as tf
  import argparse
  import os
  import cv2
  import numpy as np
  CLASSES = ('__background__',
             'aeroplane', 'bicycle', 'bird', 'boat',
             'bottle', 'bus', 'car', 'cat', 'chair',
             'cow', 'diningtable', 'dog', 'horse',
             'motorbike', 'person', 'pottedplant',
             'sheep', 'sofa', 'train', 'tvmonitor')
  
  NETS = {'vgg16': ('vgg16_faster_rcnn_iter_40000.ckpt',), 'res101': ('res101_faster_rcnn_iter_110000.ckpt',)}
  DATASETS = {'pascal_voc': ('voc_2007_trainval',), 'pascal_voc_0712': ('voc_2007_trainval+voc_2012_trainval',)}
  
  try:
      import cPickle as pickle
  except ImportError:
      import pickle
  import os
  
  from lib.utils.timer import Timer
  # from utils.cython_nms import nms, nms_new
  from lib.utils.py_cpu_nms import py_cpu_nms as nms
  from lib.utils.blob import im_list_to_blob
  
  # from model.config import cfg, get_output_dir
  from lib.config.config import get_output_dir
  from lib.config import config as cfg
  from lib.utils.bbox_transform import bbox_transform_inv
  
  def parse_args():
      """Parse input arguments."""
      parser = argparse.ArgumentParser(description='Tensorflow Faster R-CNN demo')
      parser.add_argument('--net', dest='demo_net', help='Network to use [vgg16 res101]',
                          choices=NETS.keys(), default='vgg16')
      parser.add_argument('--dataset', dest='dataset', help='Trained dataset [pascal_voc pascal_voc_0712]',
                          choices=DATASETS.keys(), default='pascal_voc')
      args = parser.parse_args()
  
      return args
  def get_training_roidb(imdb):
      """Returns a roidb (Region of Interest database) for use in training."""
      if True:
          print('Appending horizontally-flipped training examples...')
          imdb.append_flipped_images()
          print('done')
  
      print('Preparing training data...')
      rdl_roidb.prepare_roidb(imdb)
      print('done')
  
      return imdb.roidb
  
  
  def combined_roidb(imdb_names):
      """
      Combine multiple roidbs
      """
  
      def get_roidb(imdb_name):
          imdb = get_imdb(imdb_name)
          print('Loaded dataset `{:s}` for training'.format(imdb.name))
          imdb.set_proposal_method("gt")
          print('Set proposal method: {:s}'.format("gt"))
          roidb = get_training_roidb(imdb)
          return roidb
  
      roidbs = [get_roidb(s) for s in imdb_names.split('+')]
      roidb = roidbs[0]
      if len(roidbs) > 1:
          for r in roidbs[1:]:
              roidb.extend(r)
          tmp = get_imdb(imdb_names.split('+')[1])
          imdb = imdb2(imdb_names, tmp.classes)
      else:
          imdb = get_imdb(imdb_names)
      return imdb, roidb
  def _get_image_blob(im):
      """Converts an image into a network input.
      Arguments:
        im (ndarray): a color image in BGR order
      Returns:
        blob (ndarray): a data blob holding an image pyramid
        im_scale_factors (list): list of image scales (relative to im) used
          in the image pyramid
      """
      im_orig = im.astype(np.float32, copy=True)
      im_orig -= cfg.FLAGS2["pixel_means"]
      im_shape = im_orig.shape
      im_size_min = np.min(im_shape[0:2])
      im_size_max = np.max(im_shape[0:2])
  
      processed_ims = []
      im_scale_factors = []
  
      for target_size in cfg.FLAGS2["test_scales"]:
          im_scale = float(target_size) / float(im_size_min)
          # Prevent the biggest axis from being more than MAX_SIZE
          if np.round(im_scale * im_size_max) > cfg.FLAGS.test_max_size:
              im_scale = float(cfg.FLAGS.test_max_size) / float(im_size_max)
          im = cv2.resize(im_orig, None, None, fx=im_scale, fy=im_scale, interpolation=cv2.INTER_LINEAR)
          im_scale_factors.append(im_scale)
          processed_ims.append(im)
  
      # Create a blob to hold the input images
      blob = im_list_to_blob(processed_ims)
  
      return blob, np.array(im_scale_factors)
  
  
  def _get_blobs(im):
      """Convert an image and RoIs within that image into network inputs."""
      blobs = {}
      blobs['data'], im_scale_factors = _get_image_blob(im)
  
      return blobs, im_scale_factors
  
  
  def _clip_boxes(boxes, im_shape):
      """Clip boxes to image boundaries."""
      # x1 >= 0
      boxes[:, 0::4] = np.maximum(boxes[:, 0::4], 0)
      # y1 >= 0
      boxes[:, 1::4] = np.maximum(boxes[:, 1::4], 0)
      # x2 < im_shape[1]
      boxes[:, 2::4] = np.minimum(boxes[:, 2::4], im_shape[1] - 1)
      # y2 < im_shape[0]
      boxes[:, 3::4] = np.minimum(boxes[:, 3::4], im_shape[0] - 1)
      return boxes
  
  
  def _rescale_boxes(boxes, inds, scales):
      """Rescale boxes according to image rescaling."""
      for i in range(boxes.shape[0]):
          boxes[i, :] = boxes[i, :] / scales[int(inds[i])]
  
      return boxes
  
  
  def im_detect(sess, net, im):
      blobs, im_scales = _get_blobs(im)
      assert len(im_scales) == 1, "Only single-image batch implemented"
  
      im_blob = blobs['data']
      # seems to have height, width, and image scales
      # still not sure about the scale, maybe full image it is 1.
      blobs['im_info'] = np.array([[im_blob.shape[1], im_blob.shape[2], im_scales[0]]], dtype=np.float32)
  
      _, scores, bbox_pred, rois = net.test_image(sess, blobs['data'], blobs['im_info'])
  
      boxes = rois[:, 1:5] / im_scales[0]
      # print(scores.shape, bbox_pred.shape, rois.shape, boxes.shape)
      scores = np.reshape(scores, [scores.shape[0], -1])
      bbox_pred = np.reshape(bbox_pred, [bbox_pred.shape[0], -1])
      if cfg.FLAGS.test_bbox_reg:
          # Apply bounding-box regression deltas
          box_deltas = bbox_pred
          pred_boxes = bbox_transform_inv(boxes, box_deltas)
          pred_boxes = _clip_boxes(pred_boxes, im.shape)
      else:
          # Simply repeat the boxes, once for each class
          pred_boxes = np.tile(boxes, (1, scores.shape[1]))
  
      return scores, pred_boxes
  
  
  def apply_nms(all_boxes, thresh):
      """Apply non-maximum suppression to all predicted boxes output by the
      test_net method.
      """
      num_classes = len(all_boxes)
      num_images = len(all_boxes[0])
      nms_boxes = [[[] for _ in range(num_images)] for _ in range(num_classes)]
      for cls_ind in range(num_classes):
          for im_ind in range(num_images):
              dets = all_boxes[cls_ind][im_ind]
              if dets == []:
                  continue
  
              x1 = dets[:, 0]
              y1 = dets[:, 1]
              x2 = dets[:, 2]
              y2 = dets[:, 3]
              scores = dets[:, 4]
              inds = np.where((x2 > x1) & (y2 > y1) & (scores > cfg.FLAGS.DET_THRESHOLD))[0]
              dets = dets[inds, :]
              if dets == []:
                  continue
  
              keep = nms(dets, thresh)
              if len(keep) == 0:
                  continue
              nms_boxes[cls_ind][im_ind] = dets[keep, :].copy()
      return nms_boxes
  
  
  def test_net(sess, net, imdb, weights_filename, max_per_image=100, thresh=0.05):
      np.random.seed(cfg.FLAGS.rng_seed)
      """Test a Fast R-CNN network on an image database."""
      num_images = len(imdb.image_index)
      # all detections are collected into:
      #  all_boxes[cls][image] = N x 5 array of detections in
      #  (x1, y1, x2, y2, score)
      all_boxes = [[[] for _ in range(num_images)]
                   for _ in range(imdb.num_classes)]
  
      output_dir = get_output_dir(imdb, weights_filename)
      # timers
      _t = {'im_detect': Timer(), 'misc': Timer()}
  
      for i in range(num_images):
          im = cv2.imread(imdb.image_path_at(i))
  
          _t['im_detect'].tic()
          scores, boxes = im_detect(sess, net, im)
          _t['im_detect'].toc()
  
          _t['misc'].tic()
  
          # skip j = 0, because it's the background class
          for j in range(1, imdb.num_classes):
              inds = np.where(scores[:, j] > thresh)[0]
              cls_scores = scores[inds, j]
              cls_boxes = boxes[inds, j * 4:(j + 1) * 4]
              cls_dets = np.hstack((cls_boxes, cls_scores[:, np.newaxis])) \
                  .astype(np.float32, copy=False)
              keep = nms(cls_dets, 0.3)
              cls_dets = cls_dets[keep, :]
              all_boxes[j][i] = cls_dets
  
          # Limit to max_per_image detections *over all classes*
          if max_per_image > 0:
              image_scores = np.hstack([all_boxes[j][i][:, -1]
                                        for j in range(1, imdb.num_classes)])
              if len(image_scores) > max_per_image:
                  image_thresh = np.sort(image_scores)[-max_per_image]
                  for j in range(1, imdb.num_classes):
                      keep = np.where(all_boxes[j][i][:, -1] >= image_thresh)[0]
                      all_boxes[j][i] = all_boxes[j][i][keep, :]
          _t['misc'].toc()
  
          print('im_detect: {:d}/{:d} {:.3f}s {:.3f}s' \
                .format(i + 1, num_images, _t['im_detect'].average_time,
                        _t['misc'].average_time))
  
      det_file = os.path.join(output_dir, 'detections.pkl')
      with open(det_file, 'wb') as f:
          pickle.dump(all_boxes, f, pickle.HIGHEST_PROTOCOL)
  
      print('Evaluating detections')
      imdb.evaluate_detections(all_boxes, output_dir)
  if __name__ == '__main__':
      imdb, roidb = combined_roidb("voc_2007_trainval")
      data_layer = RoIDataLayer(roidb, imdb.num_classes)
      output_dir = cfg.get_output_dir(imdb, 'default')
  
      args = parse_args()
  
      # model path
      demonet = args.demo_net
      dataset = args.dataset
      # tfmodel = os.path.join('output', demonet, DATASETS[dataset][0], 'default', NETS[demonet][0])
      tfmodel = os.path.join('default', DATASETS[dataset][0], 'default', NETS[demonet][0])
  
      if not os.path.isfile(tfmodel + '.meta'):
          print(tfmodel)
          raise IOError(('{:s} not found.\nDid you download the proper networks from '
                         'our server and place them properly?').format(tfmodel + '.meta'))
  
      # set config
      tfconfig = tf.ConfigProto(allow_soft_placement=True)
      tfconfig.gpu_options.allow_growth = True
  
      # init session
      sess = tf.Session(config=tfconfig)
      # load network
      if demonet == 'vgg16':
          net = vgg16(batch_size=1)
      # elif demonet == 'res101':
          # net = resnetv1(batch_size=1, num_layers=101)
      else:
          raise NotImplementedError
  
      n_classes = len(CLASSES)
      # create the structure of the net having a certain shape (which depends on the number of classes)
      net.create_architecture(sess, "TEST", n_classes,
                              tag='default', anchor_scales=[8, 16, 32])
      saver = tf.train.Saver()
      saver.restore(sess, tfmodel)
      print('Loaded network {:s}'.format(tfmodel))
      test_net(sess, net, imdb, 'default', max_per_image=100, thresh=0.05)
  
  