Commit 47e457a5 authored by Ross Girshick's avatar Ross Girshick Committed by Facebook Github Bot

Avoid negatives areas found exception

Summary:
In some cases, eg training from scratch with a high LR or w/o activation normalization, we saw a "Negative Areas Found" exception. The RPN proposal generation code filters proposals that have a height or width that are too small. By default we use a `min_size` of 0. In a distant other part of the code, it computes the area of the proposals in order to determine FPN scale assignment. An issue arises because the `+ 1` in the `x2 - x1 + 1` width (and height) computation is not scale invariant. It turns out that the filter based on `min_size` was performed in the scaled input coordinates while the FPN scale assignment areas are computed using the unscaled, original image size. Thus a `min_size` of 0 can result in proposals with a negative area as measured wrt the original image. Uuuugh :P.

This diff addresses the issue by filtering based on the area in the unscaled input image and also using a generous (though still small) margin of 1 pixel for `min_size`.

Reviewed By: KaimingHe

Differential Revision: D8773216

fbshipit-source-id: b4ffbc5b6a831176b2656810edea3d3d4e52d687
parent e658aa86
......@@ -171,13 +171,24 @@ class GenerateProposalsOp(object):
def _filter_boxes(boxes, min_size, im_info):
"""Only keep boxes with both sides >= min_size and center within the image.
"""
# Scale min_size to match image scale
min_size *= im_info[2]
# Compute the width and height of the proposal boxes as measured in the original
# image coordinate system (this is required to avoid "Negative Areas Found"
# assertions in other parts of the code that measure).
im_scale = im_info[2]
ws_orig_scale = (boxes[:, 2] - boxes[:, 0]) / im_scale + 1
hs_orig_scale = (boxes[:, 3] - boxes[:, 1]) / im_scale + 1
# To avoid numerical issues we require the min_size to be at least 1 pixel in the
# original image
min_size = np.maximum(min_size, 1)
# Proposal center is computed relative to the scaled input image
ws = boxes[:, 2] - boxes[:, 0] + 1
hs = boxes[:, 3] - boxes[:, 1] + 1
x_ctr = boxes[:, 0] + ws / 2.
y_ctr = boxes[:, 1] + hs / 2.
keep = np.where(
(ws >= min_size) & (hs >= min_size) &
(x_ctr < im_info[1]) & (y_ctr < im_info[0]))[0]
(ws_orig_scale >= min_size)
& (hs_orig_scale >= min_size)
& (x_ctr < im_info[1])
& (y_ctr < im_info[0])
)[0]
return keep
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment