|
|
@ -21,7 +21,6 @@ import math
|
|
|
|
import paddle
|
|
|
|
import paddle
|
|
|
|
import paddle.fluid as fluid
|
|
|
|
import paddle.fluid as fluid
|
|
|
|
from op_test import OpTest
|
|
|
|
from op_test import OpTest
|
|
|
|
from test_multiclass_nms_op import nms
|
|
|
|
|
|
|
|
from test_anchor_generator_op import anchor_generator_in_python
|
|
|
|
from test_anchor_generator_op import anchor_generator_in_python
|
|
|
|
import copy
|
|
|
|
import copy
|
|
|
|
from test_generate_proposals_op import clip_tiled_boxes, box_coder, nms
|
|
|
|
from test_generate_proposals_op import clip_tiled_boxes, box_coder, nms
|
|
|
@ -29,7 +28,7 @@ from test_generate_proposals_op import clip_tiled_boxes, box_coder, nms
|
|
|
|
|
|
|
|
|
|
|
|
def generate_proposals_v2_in_python(scores, bbox_deltas, im_shape, anchors,
|
|
|
|
def generate_proposals_v2_in_python(scores, bbox_deltas, im_shape, anchors,
|
|
|
|
variances, pre_nms_topN, post_nms_topN,
|
|
|
|
variances, pre_nms_topN, post_nms_topN,
|
|
|
|
nms_thresh, min_size, eta):
|
|
|
|
nms_thresh, min_size, eta, pixel_offset):
|
|
|
|
all_anchors = anchors.reshape(-1, 4)
|
|
|
|
all_anchors = anchors.reshape(-1, 4)
|
|
|
|
rois = np.empty((0, 5), dtype=np.float32)
|
|
|
|
rois = np.empty((0, 5), dtype=np.float32)
|
|
|
|
roi_probs = np.empty((0, 1), dtype=np.float32)
|
|
|
|
roi_probs = np.empty((0, 1), dtype=np.float32)
|
|
|
@ -42,7 +41,8 @@ def generate_proposals_v2_in_python(scores, bbox_deltas, im_shape, anchors,
|
|
|
|
img_i_boxes, img_i_probs = proposal_for_one_image(
|
|
|
|
img_i_boxes, img_i_probs = proposal_for_one_image(
|
|
|
|
im_shape[img_idx, :], all_anchors, variances,
|
|
|
|
im_shape[img_idx, :], all_anchors, variances,
|
|
|
|
bbox_deltas[img_idx, :, :, :], scores[img_idx, :, :, :],
|
|
|
|
bbox_deltas[img_idx, :, :, :], scores[img_idx, :, :, :],
|
|
|
|
pre_nms_topN, post_nms_topN, nms_thresh, min_size, eta)
|
|
|
|
pre_nms_topN, post_nms_topN, nms_thresh, min_size, eta,
|
|
|
|
|
|
|
|
pixel_offset)
|
|
|
|
rois_num.append(img_i_probs.shape[0])
|
|
|
|
rois_num.append(img_i_probs.shape[0])
|
|
|
|
rpn_rois.append(img_i_boxes)
|
|
|
|
rpn_rois.append(img_i_boxes)
|
|
|
|
rpn_roi_probs.append(img_i_probs)
|
|
|
|
rpn_roi_probs.append(img_i_probs)
|
|
|
@ -52,7 +52,7 @@ def generate_proposals_v2_in_python(scores, bbox_deltas, im_shape, anchors,
|
|
|
|
|
|
|
|
|
|
|
|
def proposal_for_one_image(im_shape, all_anchors, variances, bbox_deltas,
|
|
|
|
def proposal_for_one_image(im_shape, all_anchors, variances, bbox_deltas,
|
|
|
|
scores, pre_nms_topN, post_nms_topN, nms_thresh,
|
|
|
|
scores, pre_nms_topN, post_nms_topN, nms_thresh,
|
|
|
|
min_size, eta):
|
|
|
|
min_size, eta, pixel_offset):
|
|
|
|
# Transpose and reshape predicted bbox transformations to get them
|
|
|
|
# Transpose and reshape predicted bbox transformations to get them
|
|
|
|
# into the same order as the anchors:
|
|
|
|
# into the same order as the anchors:
|
|
|
|
# - bbox deltas will be (4 * A, H, W) format from conv output
|
|
|
|
# - bbox deltas will be (4 * A, H, W) format from conv output
|
|
|
@ -83,12 +83,12 @@ def proposal_for_one_image(im_shape, all_anchors, variances, bbox_deltas,
|
|
|
|
scores = scores[order, :]
|
|
|
|
scores = scores[order, :]
|
|
|
|
bbox_deltas = bbox_deltas[order, :]
|
|
|
|
bbox_deltas = bbox_deltas[order, :]
|
|
|
|
all_anchors = all_anchors[order, :]
|
|
|
|
all_anchors = all_anchors[order, :]
|
|
|
|
proposals = box_coder(all_anchors, bbox_deltas, variances)
|
|
|
|
proposals = box_coder(all_anchors, bbox_deltas, variances, pixel_offset)
|
|
|
|
# clip proposals to image (may result in proposals with zero area
|
|
|
|
# clip proposals to image (may result in proposals with zero area
|
|
|
|
# that will be removed in the next step)
|
|
|
|
# that will be removed in the next step)
|
|
|
|
proposals = clip_tiled_boxes(proposals, im_shape)
|
|
|
|
proposals = clip_tiled_boxes(proposals, im_shape, pixel_offset)
|
|
|
|
# remove predicted boxes with height or width < min_size
|
|
|
|
# remove predicted boxes with height or width < min_size
|
|
|
|
keep = filter_boxes(proposals, min_size, im_shape)
|
|
|
|
keep = filter_boxes(proposals, min_size, im_shape, pixel_offset)
|
|
|
|
if len(keep) == 0:
|
|
|
|
if len(keep) == 0:
|
|
|
|
proposals = np.zeros((1, 4)).astype('float32')
|
|
|
|
proposals = np.zeros((1, 4)).astype('float32')
|
|
|
|
scores = np.zeros((1, 1)).astype('float32')
|
|
|
|
scores = np.zeros((1, 1)).astype('float32')
|
|
|
@ -103,7 +103,8 @@ def proposal_for_one_image(im_shape, all_anchors, variances, bbox_deltas,
|
|
|
|
keep = nms(boxes=proposals,
|
|
|
|
keep = nms(boxes=proposals,
|
|
|
|
scores=scores,
|
|
|
|
scores=scores,
|
|
|
|
nms_threshold=nms_thresh,
|
|
|
|
nms_threshold=nms_thresh,
|
|
|
|
eta=eta)
|
|
|
|
eta=eta,
|
|
|
|
|
|
|
|
pixel_offset=pixel_offset)
|
|
|
|
if post_nms_topN > 0 and post_nms_topN < len(keep):
|
|
|
|
if post_nms_topN > 0 and post_nms_topN < len(keep):
|
|
|
|
keep = keep[:post_nms_topN]
|
|
|
|
keep = keep[:post_nms_topN]
|
|
|
|
proposals = proposals[keep, :]
|
|
|
|
proposals = proposals[keep, :]
|
|
|
@ -112,17 +113,21 @@ def proposal_for_one_image(im_shape, all_anchors, variances, bbox_deltas,
|
|
|
|
return proposals, scores
|
|
|
|
return proposals, scores
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def filter_boxes(boxes, min_size, im_shape):
|
|
|
|
def filter_boxes(boxes, min_size, im_shape, pixel_offset=True):
|
|
|
|
"""Only keep boxes with both sides >= min_size and center within the image.
|
|
|
|
"""Only keep boxes with both sides >= min_size and center within the image.
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
# Scale min_size to match image scale
|
|
|
|
# Scale min_size to match image scale
|
|
|
|
min_size = max(min_size, 1.0)
|
|
|
|
min_size = max(min_size, 1.0)
|
|
|
|
ws = boxes[:, 2] - boxes[:, 0] + 1
|
|
|
|
offset = 1 if pixel_offset else 0
|
|
|
|
hs = boxes[:, 3] - boxes[:, 1] + 1
|
|
|
|
ws = boxes[:, 2] - boxes[:, 0] + offset
|
|
|
|
x_ctr = boxes[:, 0] + ws / 2.
|
|
|
|
hs = boxes[:, 3] - boxes[:, 1] + offset
|
|
|
|
y_ctr = boxes[:, 1] + hs / 2.
|
|
|
|
if pixel_offset:
|
|
|
|
keep = np.where((ws >= min_size) & (hs >= min_size) & (x_ctr < im_shape[1])
|
|
|
|
x_ctr = boxes[:, 0] + ws / 2.
|
|
|
|
& (y_ctr < im_shape[0]))[0]
|
|
|
|
y_ctr = boxes[:, 1] + hs / 2.
|
|
|
|
|
|
|
|
keep = np.where((ws >= min_size) & (hs >= min_size) & (x_ctr < im_shape[
|
|
|
|
|
|
|
|
1]) & (y_ctr < im_shape[0]))[0]
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
keep = np.where((ws >= min_size) & (hs >= min_size))[0]
|
|
|
|
return keep
|
|
|
|
return keep
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -144,7 +149,8 @@ class TestGenerateProposalsV2Op(OpTest):
|
|
|
|
'post_nms_topN': self.post_nms_topN,
|
|
|
|
'post_nms_topN': self.post_nms_topN,
|
|
|
|
'nms_thresh': self.nms_thresh,
|
|
|
|
'nms_thresh': self.nms_thresh,
|
|
|
|
'min_size': self.min_size,
|
|
|
|
'min_size': self.min_size,
|
|
|
|
'eta': self.eta
|
|
|
|
'eta': self.eta,
|
|
|
|
|
|
|
|
'pixel_offset': self.pixel_offset,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
self.outputs = {
|
|
|
|
self.outputs = {
|
|
|
@ -165,6 +171,7 @@ class TestGenerateProposalsV2Op(OpTest):
|
|
|
|
self.nms_thresh = 0.7
|
|
|
|
self.nms_thresh = 0.7
|
|
|
|
self.min_size = 3.0
|
|
|
|
self.min_size = 3.0
|
|
|
|
self.eta = 1.
|
|
|
|
self.eta = 1.
|
|
|
|
|
|
|
|
self.pixel_offset = True
|
|
|
|
|
|
|
|
|
|
|
|
def init_test_input(self):
|
|
|
|
def init_test_input(self):
|
|
|
|
batch_size = 1
|
|
|
|
batch_size = 1
|
|
|
@ -191,7 +198,7 @@ class TestGenerateProposalsV2Op(OpTest):
|
|
|
|
self.rpn_rois, self.rpn_roi_probs, self.rois_num = generate_proposals_v2_in_python(
|
|
|
|
self.rpn_rois, self.rpn_roi_probs, self.rois_num = generate_proposals_v2_in_python(
|
|
|
|
self.scores, self.bbox_deltas, self.im_shape, self.anchors,
|
|
|
|
self.scores, self.bbox_deltas, self.im_shape, self.anchors,
|
|
|
|
self.variances, self.pre_nms_topN, self.post_nms_topN,
|
|
|
|
self.variances, self.pre_nms_topN, self.post_nms_topN,
|
|
|
|
self.nms_thresh, self.min_size, self.eta)
|
|
|
|
self.nms_thresh, self.min_size, self.eta, self.pixel_offset)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestGenerateProposalsV2OutLodOp(TestGenerateProposalsV2Op):
|
|
|
|
class TestGenerateProposalsV2OutLodOp(TestGenerateProposalsV2Op):
|
|
|
@ -231,6 +238,17 @@ class TestGenerateProposalsV2OpNoBoxLeft(TestGenerateProposalsV2Op):
|
|
|
|
self.nms_thresh = 0.7
|
|
|
|
self.nms_thresh = 0.7
|
|
|
|
self.min_size = 1000.0
|
|
|
|
self.min_size = 1000.0
|
|
|
|
self.eta = 1.
|
|
|
|
self.eta = 1.
|
|
|
|
|
|
|
|
self.pixel_offset = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestGenerateProposalsV2OpNoOffset(TestGenerateProposalsV2Op):
|
|
|
|
|
|
|
|
def init_test_params(self):
|
|
|
|
|
|
|
|
self.pre_nms_topN = 12000 # train 12000, test 2000
|
|
|
|
|
|
|
|
self.post_nms_topN = 5000 # train 6000, test 1000
|
|
|
|
|
|
|
|
self.nms_thresh = 0.7
|
|
|
|
|
|
|
|
self.min_size = 3.0
|
|
|
|
|
|
|
|
self.eta = 1.
|
|
|
|
|
|
|
|
self.pixel_offset = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
if __name__ == '__main__':
|
|
|
|