//  [python]
def build_whole_detection_network(self, input_img_batch, gtboxes_batch_h, gtboxes_batch_r, gt_smooth_label, gpu_id=0):

        if self.is_training:
            gtboxes_batch_h = tf.reshape(gtboxes_batch_h, [-1, 5])
            gtboxes_batch_h = tf.cast(gtboxes_batch_h, tf.float32)

            gtboxes_batch_r = tf.reshape(gtboxes_batch_r, [-1, 6])
            gtboxes_batch_r = tf.cast(gtboxes_batch_r, tf.float32)

            gt_smooth_label = tf.reshape(gt_smooth_label, [-1, self.angle_range])
            gt_smooth_label = tf.cast(gt_smooth_label, tf.float32)

        img_shape = tf.shape(input_img_batch)

        # 1. build base network
        feature_pyramid = self.build_base_network(input_img_batch)

        # 2. build rpn
        rpn_box_pred_list, rpn_cls_score_list, rpn_cls_prob_list = self.rpn_net(feature_pyramid, 'rpn_net')

        # 3. generate_anchors
        anchor_list = self.make_anchors(feature_pyramid)

        rpn_box_pred = tf.concat(rpn_box_pred_list, axis=0)
        rpn_cls_score = tf.concat(rpn_cls_score_list, axis=0)
        # rpn_cls_prob = tf.concat(rpn_cls_prob_list, axis=0)
        anchors = tf.concat(anchor_list, axis=0)

        if self.is_training:
            with tf.variable_scope('build_loss'):
                labels, target_delta, anchor_states, target_boxes = tf.py_func(func=anchor_target_layer,
                                                                               inp=[gtboxes_batch_h, gtboxes_batch_r,
                                                                                    anchors, gpu_id],
                                                                               Tout=[tf.float32, tf.float32,
                                                                                     tf.float32, tf.float32])

                if self.method == 'H':
                    self.add_anchor_img_smry(input_img_batch, anchors, anchor_states, 0)
                else:
                    self.add_anchor_img_smry(input_img_batch, anchors, anchor_states, 1)

                cls_loss = losses.focal_loss(labels, rpn_cls_score, anchor_states)
                if cfgs.USE_IOU_FACTOR:
                    reg_loss = losses.iou_smooth_l1_loss_(target_delta, rpn_box_pred, anchor_states, target_boxes, anchors)
                    # reg_loss = losses.iou_smooth_l1_loss_1(rpn_box_pred, anchor_states, target_boxes,
                    #                                        anchors)
                else:
                    reg_loss = losses.smooth_l1_loss(target_delta, rpn_box_pred, anchor_states)

                self.losses_dict['cls_loss'] = cls_loss * cfgs.CLS_WEIGHT
                self.losses_dict['reg_loss'] = reg_loss * cfgs.REG_WEIGHT

        box_pred_list, cls_prob_list, proposal_list, angle_cls_list = rpn_box_pred_list, rpn_cls_prob_list, anchor_list, [None, None, None, None, None]

        all_box_pred_list, all_cls_prob_list, all_proposal_list, all_angle_cls_list = [], [], [], []

        for i in range(cfgs.NUM_REFINE_STAGE):
            box_pred_list, cls_prob_list, proposal_list, angle_cls_list = self.refine_stage(input_img_batch,
                                                                                            gtboxes_batch_r,
                                                                                            gt_smooth_label,
                                                                                            box_pred_list,
                                                                                            cls_prob_list,
                                                                                            proposal_list,
                                                                                            angle_cls_list,
                                                                                            feature_pyramid,
                                                                                            gpu_id,
                                                                                            pos_threshold=cfgs.REFINE_IOU_POSITIVE_THRESHOLD[i],
                                                                                            neg_threshold=cfgs.REFINE_IOU_NEGATIVE_THRESHOLD[i],
                                                                                            stage='' if i == 0 else '_stage{}'.format(i + 2),
                                                                                            proposal_filter=True if i == 0 else False)

            if not self.is_training:
                all_box_pred_list.extend(box_pred_list)
                all_cls_prob_list.extend(cls_prob_list)
                all_proposal_list.extend(proposal_list)
                all_angle_cls_list.extend(angle_cls_list)
            else:
                all_box_pred_list, all_cls_prob_list, all_proposal_list, all_angle_cls_list = box_pred_list, cls_prob_list, proposal_list, angle_cls_list

        with tf.variable_scope('postprocess_detctions'):
            box_pred = tf.concat(all_box_pred_list, axis=0)
            cls_prob = tf.concat(all_cls_prob_list, axis=0)
            proposal = tf.concat(all_proposal_list, axis=0)
            angle_cls = tf.concat(all_angle_cls_list, axis=0)

            boxes, scores, category, boxes_angle = postprocess_detctions(refine_bbox_pred=box_pred,
                                                                         refine_cls_prob=cls_prob,
                                                                         refine_angle_prob=tf.sigmoid(angle_cls),
                                                                         anchors=proposal,
                                                                         is_training=self.is_training,
                                                                         gpu_id=gpu_id)

            boxes = tf.stop_gradient(boxes)
            scores = tf.stop_gradient(scores)
            category = tf.stop_gradient(category)
            boxes_angle = tf.stop_gradient(boxes_angle)

        if self.is_training:
            return boxes, scores, category, boxes_angle, self.losses_dict
        else:
            return boxes, scores, category, boxes_angle