def getBoxes(self, proposals, proposal_scores, maxOutputs=30, nmsThreshold=0.3, scoreThreshold=0.8): if scoreThreshold is None: scoreThreshold = 0 with tf.name_scope("getBoxes"): scores = tf.nn.softmax(self.getBoxScores(proposals)) classes = tf.argmax(scores, 1) scores = tf.reduce_max(scores, axis=1) posIndices = tf.cast( tf.where(tf.logical_and(classes > 0, scores > scoreThreshold)), tf.int32) positives, scores, classes = MultiGather.gather( [proposals, scores, classes], posIndices) positives = self.refineBoxes(positives)[0] #Final NMS posIndices = tf.image.non_max_suppression( positives, scores, iou_threshold=nmsThreshold, max_output_size=maxOutputs) posIndices = tf.expand_dims(posIndices, axis=-1) positives, scores, classes = MultiGather.gather( [positives, scores, classes], posIndices) classes = tf.cast(tf.cast(classes, tf.int32) - 1, tf.uint8) return positives, scores, classes
def filterOutputBoxes(self, boxes, scores, others=[], preNmsCount=6000, maxOutSize=300, nmsThreshold=0.7): with tf.name_scope("filter_output_boxes"): scores = tf.nn.softmax(scores)[:, 1] scores = tf.reshape(scores, [-1]) #Clip boxes to edge boxes = self.clipBoxesToEdge(boxes) #Remove empty boxes boxes, scores = BoxUtils.filterSmallBoxes(boxes, [scores]) scores, boxes = tf.cond( tf.shape(scores)[0] > preNmsCount, lambda: tf.tuple( MultiGather.gatherTopK(scores, preNmsCount, [boxes])), lambda: tf.tuple([scores, boxes])) #NMS filter nmsIndices = tf.image.non_max_suppression( boxes, scores, iou_threshold=nmsThreshold, max_output_size=maxOutSize) nmsIndices = tf.expand_dims(nmsIndices, axis=-1) return MultiGather.gather([boxes, scores] + others, nmsIndices)
def getPosLoss(positiveBoxes, positiveRefIndices, nPositive): with tf.name_scope("getPosLoss"): positiveRefIndices = tf.reshape(positiveRefIndices,[-1,1]) positiveClasses, positiveRefBoxes = MultiGather.gather([refClasses, refBoxes], positiveRefIndices) positiveClasses = tf.cast(tf.cast(positiveClasses,tf.int8) + 1, tf.uint8) if not self.hardMining: selected = Utils.RandomSelect.randomSelectIndex(tf.shape(positiveBoxes)[0], nPositive) positiveBoxes, positiveClasses, positiveRefBoxes = MultiGather.gather([positiveBoxes, positiveClasses, positiveRefBoxes], selected) return tf.tuple([self.classRefinementLoss(positiveBoxes, positiveClasses) + self.boxRefinementLoss(positiveBoxes, positiveRefBoxes), tf.shape(positiveBoxes)[0]])
def getPositiveLoss(boxes, rawSizes, boxSizes, positiveIndices, bestIou, classificationLoss): with tf.name_scope('getPositiveLoss'): positiveBoxes, positiveRawSizes, positiveBoxSizes, positiveRefIndices, positiveClassificationLoss = \ MultiGather.gather([boxes, rawSizes, boxSizes, bestIou, classificationLoss], positiveIndices) #Regression loss positiveRefs = tf.gather_nd(refBoxes, positiveRefIndices) return Loss.boxRegressionLoss(positiveBoxes, positiveRawSizes, positiveRefs, positiveBoxSizes)*self.regressionWeight + positiveClassificationLoss
def getRefinementLoss(): with tf.name_scope("getRefinementLoss"): iou = BoxUtils.iou(proposals, refBoxes) maxIou = tf.reduce_max(iou, axis=1) bestIou = tf.expand_dims(tf.cast(tf.argmax(iou, axis=1), tf.int32), axis=-1) #Find positive and negative indices based on their IOU posBoxIndices = tf.cast(tf.where(maxIou > self.posIouTheshold), tf.int32) negBoxIndices = tf.cast(tf.where(tf.logical_and(maxIou < self.negIouThesholdHi, maxIou > self.negIouThesholdLo)), tf.int32) #Split the boxes and references posBoxes, posRefIndices = MultiGather.gather([proposals, bestIou], posBoxIndices) negBoxes = tf.gather_nd(proposals, negBoxIndices) #Add GT boxes posBoxes = tf.concat([posBoxes,refBoxes], 0) posRefIndices = tf.concat([posRefIndices, tf.reshape(tf.range(tf.shape(refClasses)[0]), [-1,1])], 0) #Call the loss if the box collection is not empty nPositive = tf.shape(posBoxes)[0] nNegative = tf.shape(negBoxes)[0] if self.hardMining: posLoss = tf.cond(nPositive > 0, lambda: getPosLoss(posBoxes, posRefIndices, 0)[0], lambda: tf.zeros((0,), tf.float32)) negLoss = tf.cond(nNegative > 0, lambda: getNegLoss(negBoxes, 0), lambda: tf.zeros((0,), tf.float32)) allLoss = tf.concat([posLoss, negLoss], 0) return tf.cond(tf.shape(allLoss)[0]>0, lambda: tf.reduce_mean(Utils.MultiGather.gatherTopK(allLoss, self.nTrainBoxes)), lambda: tf.constant(0.0)) else: posLoss, posCount = tf.cond(nPositive > 0, lambda: getPosLoss(posBoxes, posRefIndices, self.nTrainPositives), lambda: tf.tuple([tf.constant(0.0), tf.constant(0,tf.int32)])) negLoss = tf.cond(nNegative > 0, lambda: getNegLoss(negBoxes, self.nTrainBoxes-posCount), lambda: tf.constant(0.0)) nPositive = tf.cast(tf.shape(posLoss)[0], tf.float32) nNegative = tf.cond(nNegative > 0, lambda: tf.cast(tf.shape(negLoss)[0], tf.float32), lambda: tf.constant(0.0)) return (tf.reduce_mean(posLoss)*nPositive + tf.reduce_mean(negLoss)*nNegative)/(nNegative+nPositive)
def filterCrossBoundaryBoxes(self, boxes, others=[], boxInsideRate=1.0): with tf.name_scope('filterCrossBoundaryBoxes'): okIndices = tf.where(self.getInsideMask(boxes, boxInsideRate)) okIndices = tf.cast(okIndices, tf.int32) return MultiGather.gather([boxes]+others, okIndices)