Mask rcnn can not detect ROI class probability, the probability is background all the time

AdamLin: <p>Dear,<br>
I’m going to use Mask rcnn inference demo with pre-trained model using image of COCO dataset<br>
I’m following this : <a href="https://github.com/multimodallearning/pytorch-mask-rcnn" class="inline-onebox" rel="noopener nofollow ugc">GitHub - multimodallearning/pytorch-mask-rcnn</a></p>
<p>Replace C++ embeding python. NMS and ROIalign<br>
by torchvision.ops.nms() and torchvision.ops.roi_align()</p>
<p>My config is : python 3.8 torch 1.9.1+cu111, torchvision 0.10.1+cu111</p>
<p>In the “FPN Head classifier”  detect ROI  mrcnn probalitity always is background<br>
So next step that refine the ROI,<br>
class probability of the top class of each ROI, filter out background boxes is error<br>
because all class probability are background</p>
<p>The error code is :<br>
D:\Ru\pytorch-mask-rcnn\test\model_1028.py:1687: UserWarning: volatile was removed and now has no effect. Use <code>with torch.no_grad():</code> instead.<br>
molded_images = Variable(molded_images, volatile=True)<br>
C:\Users\admin\anaconda3\envs\torch\lib\site-packages\torch\nn\functional.py:3487: UserWarning: nn.functional.upsample is deprecated. Use nn.functional.interpolate instead.<br>
warnings.warn(“nn.functional.upsample is deprecated. Use nn.functional.interpolate instead.”)<br>
Traceback (most recent call last):<br>
File “D:/Ru/pytorch-mask-rcnn/test/demo_1028.py”, line 99, in <br>
results = model.detect([image])<br>
File “D:\Ru\pytorch-mask-rcnn\test\model_1028.py”, line 1690, in detect<br>
detections, mrcnn_mask = self.predict([molded_images, image_metas], mode=‘inference’)<br>
File “D:\Ru\pytorch-mask-rcnn\test\model_1028.py”, line 1766, in predict<br>
detections = detection_layer(self.config, rpn_rois, mrcnn_class, mrcnn_bbox, image_metas)<br>
File “D:\Ru\pytorch-mask-rcnn\test\model_1028.py”, line 919, in detection_layer<br>
detections = refine_detections(rois, mrcnn_class, mrcnn_bbox, window, config)<br>
File “D:\Ru\pytorch-mask-rcnn\test\model_1028.py”, line 890, in refine_detections<br>
keep = intersect1d(keep, nms_keep)<br>
UnboundLocalError: local variable ‘nms_keep’ referenced before assignment</p>
<p>What do you think? What’s happening?</p>

ptrblck: <aside class="quote no-group" data-username="AdamLin" data-post="1" data-topic="135456">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/adamlin/48/43406_2.png" class="avatar"> AdamLin:</div>
<blockquote>
<p>UnboundLocalError: local variable ‘nms_keep’ referenced before assignment</p>
</blockquote>
</aside>
<p>This error claims that <code>nms_keep</code> is used before its creation/assignmen, so check your code and make sure <code>nms_keep</code> is properly initialized before its usage. This is often caused when variables are initialized inside an <code>if</code> condition, which is then never triggered.</p>

AdamLin: <p>Thanks for reply<br>
The nms_keep is create after if condition</p>
<pre><code class="lang-auto">def refine_detections(rois, probs, deltas, window, config):
    """Refine classified proposals and filter overlaps and return final
    detections.

    Inputs:
        rois: [N, (y1, x1, y2, x2)] in normalized coordinates
        probs: [N, num_classes]. Class probabilities.
        deltas: [N, num_classes, (dy, dx, log(dh), log(dw))]. Class-specific
                bounding box deltas.
        window: (y1, x1, y2, x2) in image coordinates. The part of the image
            that contains the image excluding the padding.

    Returns detections shaped: [N, (y1, x1, y2, x2, class_id, score)]
    """

    # Class IDs per ROI
    _, class_ids = torch.max(probs, dim=1)

    # Class probability of the top class of each ROI
    # Class-specific bounding box deltas
    idx = torch.arange(class_ids.size()[0]).long()
    if config.GPU_COUNT:
        idx = idx.cuda()
    class_scores = probs[idx, class_ids.data]
    deltas_specific = deltas[idx, class_ids.data]

    # Apply bounding box deltas
    # Shape: [boxes, (y1, x1, y2, x2)] in normalized coordinates
    std_dev = Variable(torch.from_numpy(np.reshape(config.RPN_BBOX_STD_DEV, [1, 4])).float(), requires_grad=False)
    if config.GPU_COUNT:
        std_dev = std_dev.cuda()
    refined_rois = apply_box_deltas(rois, deltas_specific * std_dev)

    # Convert coordiates to image domain
    height, width = config.IMAGE_SHAPE[:2]
    scale = Variable(torch.from_numpy(np.array([height, width, height, width])).float(), requires_grad=False)
    if config.GPU_COUNT:
        scale = scale.cuda()
    refined_rois *= scale

    # Clip boxes to image window
    refined_rois = clip_to_window(window, refined_rois)

    # Round and cast to int since we're deadling with pixels now
    refined_rois = torch.round(refined_rois)

    # TODO: Filter out boxes with zero area

    # Filter out background boxes
    keep_bool = class_ids&gt;0

    # Filter out low confidence boxes
    if config.DETECTION_MIN_CONFIDENCE:
        keep_bool = keep_bool &amp; (class_scores &gt;= config.DETECTION_MIN_CONFIDENCE)
    keep = torch.nonzero(keep_bool)[:,0]

    # Apply per-class NMS
    pre_nms_class_ids = class_ids[keep.data]
    pre_nms_scores = class_scores[keep.data]
    pre_nms_rois = refined_rois[keep.data]

    for i, class_id in enumerate(unique1d(pre_nms_class_ids)):
        # Pick detections of this class
        ixs = torch.nonzero(pre_nms_class_ids == class_id)[:,0]

        # Sort
        ix_rois = pre_nms_rois[ixs.data]
        ix_scores = pre_nms_scores[ixs]
        ix_scores, order = ix_scores.sort(descending=True)
        ix_rois = ix_rois[order.data,:]

        # class_keep = nms(torch.cat((ix_rois, ix_scores.unsqueeze(1)), dim=1).data, config.DETECTION_NMS_THRESHOLD)
        class_keep = torchvision.ops.nms(ix_rois, ix_scores, config.DETECTION_NMS_THRESHOLD)

        # Map indicies
        class_keep = keep[ixs[order[class_keep].data].data]

        if i==0:
            nms_keep = class_keep
        else:
            nms_keep = unique1d(torch.cat((nms_keep, class_keep)))
    keep = intersect1d(keep, nms_keep)
</code></pre>
<p>This is my code.</p>
<p>In the  Filter out background boxes part</p>
<pre><code class="lang-auto">    keep_bool = class_ids&gt;0
</code></pre>
<p>All of class_ids are zero<br>
I feel weird</p>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/6/6/667c5709c9c09abf788ca7aad53ac3284f5935fe.png" data-download-href="https://discuss.pytorch.org/uploads/default/667c5709c9c09abf788ca7aad53ac3284f5935fe" title="Screenshot_3"><img src="https://discuss.pytorch.org/uploads/default/optimized/3X/6/6/667c5709c9c09abf788ca7aad53ac3284f5935fe_2_690x361.png" alt="Screenshot_3" data-base62-sha1="eCD69ikvJKqW1ZTKLdthAQtsFyK" width="690" height="361" srcset="https://discuss.pytorch.org/uploads/default/optimized/3X/6/6/667c5709c9c09abf788ca7aad53ac3284f5935fe_2_690x361.png, https://discuss.pytorch.org/uploads/default/optimized/3X/6/6/667c5709c9c09abf788ca7aad53ac3284f5935fe_2_1035x541.png 1.5x, https://discuss.pytorch.org/uploads/default/optimized/3X/6/6/667c5709c9c09abf788ca7aad53ac3284f5935fe_2_1380x722.png 2x" data-dominant-color="EBECED"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">Screenshot_3</span><span class="informations">1529×801 84.4 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>

AdamLin: <pre><code class="lang-auto">############################################################
#  Feature Pyramid Network Heads
############################################################

class Classifier(nn.Module):
    def __init__(self, depth, pool_size, image_shape, num_classes):
        super(Classifier, self).__init__()
        self.depth = depth
        self.pool_size = pool_size
        self.image_shape = image_shape
        self.num_classes = num_classes
        self.conv1 = nn.Conv2d(self.depth, 1024, kernel_size=self.pool_size, stride=1)
        self.bn1 = nn.BatchNorm2d(1024, eps=0.001, momentum=0.01)
        self.conv2 = nn.Conv2d(1024, 1024, kernel_size=1, stride=1)
        # self.conv2 = nn.Conv2d(self.depth, 1024, kernel_size=1, stride=1)
        self.bn2 = nn.BatchNorm2d(1024, eps=0.001, momentum=0.01)
        self.relu = nn.ReLU(inplace=True)
        self.linear_class = nn.Linear(1024, num_classes)
        self.softmax = nn.Softmax(dim=1)
        self.linear_bbox = nn.Linear(1024, num_classes * 4)

    def forward(self, x, rois):
        x = pyramid_roi_align([rois]+x, self.pool_size, self.image_shape)
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu(x)

        x = x.view(-1, 1024)
        mrcnn_class_logits = self.linear_class(x)
        mrcnn_probs = self.softmax(mrcnn_class_logits)

        mrcnn_bbox = self.linear_bbox(x)
        mrcnn_bbox = mrcnn_bbox.view(mrcnn_bbox.size()[0], -1, 4)

        return [mrcnn_class_logits, mrcnn_probs, mrcnn_bbox]

</code></pre>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/4/d/4d1bc2372937559f7efff6cbd3c20f69d9ad6455.png" data-download-href="https://discuss.pytorch.org/uploads/default/4d1bc2372937559f7efff6cbd3c20f69d9ad6455" title="Screenshot_4"><img src="https://discuss.pytorch.org/uploads/default/optimized/3X/4/d/4d1bc2372937559f7efff6cbd3c20f69d9ad6455_2_690x352.png" alt="Screenshot_4" data-base62-sha1="b08eKml9CynO0USa7wV4RocJTsp" width="690" height="352" srcset="https://discuss.pytorch.org/uploads/default/optimized/3X/4/d/4d1bc2372937559f7efff6cbd3c20f69d9ad6455_2_690x352.png, https://discuss.pytorch.org/uploads/default/optimized/3X/4/d/4d1bc2372937559f7efff6cbd3c20f69d9ad6455_2_1035x528.png 1.5x, https://discuss.pytorch.org/uploads/default/optimized/3X/4/d/4d1bc2372937559f7efff6cbd3c20f69d9ad6455_2_1380x704.png 2x" data-dominant-color="E8E9EC"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">Screenshot_4</span><span class="informations">1553×794 101 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>

ptrblck: <p>As previously described, often wrong if conditions are used which are never met. In your case this also seems to be the case here:</p>
<pre><code class="lang-python">        if i==0:
            nms_keep = class_keep
        else:
            nms_keep = unique1d(torch.cat((nms_keep, class_keep)))
</code></pre>
<p>Add a print statement to the <code>if i==0</code> case and you would see that it most likely won’t be executed before the <code>else</code> branch.</p>

AdamLin: <p>Umm…<br>
I think this issue is from architecture.<br>
Do you understand Mask rcnn how to work?</p>
<pre><code class="lang-auto">############################################################
#  Feature Pyramid Network Heads
############################################################
x = x.view(-1, 1024)
        mrcnn_class_logits = self.linear_class(x)
        mrcnn_probs = self.softmax(mrcnn_class_logits)
</code></pre>
<p>All of  mrcnn_probability are background.</p>
<pre><code class="lang-auto">def refine_detections(rois, probs, deltas, window, config):
# Class IDs per ROI
    _, class_ids = torch.max(probs, dim=1)
</code></pre>
<p>The background class_id is 0<br>
So input to next step, can not  filter out background.</p>
<p>Thanks again for your support.  I feel helpless.</p>