File size: 3,876 Bytes
25cae60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# Copyright 2021 - Valeo Comfort and Driving Assistance - Oriane Siméoni @ valeo.ai
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Code adapted from previous method LOST: https://github.com/valeoai/LOST
"""

import os
import time
import torch
import torch.nn as nn
import numpy as np

from tqdm import tqdm
from misc import bbox_iou, get_bbox_from_segmentation_labels


def evaluation_unsupervised_object_discovery(
    dataset,
    model,
    evaluation_mode: str = 'single', # choices are ["single", "multi"]
    output_dir:str = "outputs",
    no_hards:bool = False,
):
    
    assert evaluation_mode == "single"

    sigmoid = nn.Sigmoid()

    # ----------------------------------------------------
    # Loop over images
    preds_dict = {}
    cnt = 0
    corloc = np.zeros(len(dataset.dataloader))

    start_time = time.time()
    pbar = tqdm(dataset.dataloader)
    for im_id, inp in enumerate(pbar):

        # ------------ IMAGE PROCESSING -------------------------------------------
        img = inp[0]

        init_image_size = img.shape

        # Get the name of the image
        im_name = dataset.get_image_name(inp[1])
        # Pass in case of no gt boxes in the image
        if im_name is None:
            continue

        # Padding the image with zeros to fit multiple of patch-size
        size_im = (
            img.shape[0],
            int(np.ceil(img.shape[1] / model.vit_patch_size) * model.vit_patch_size),
            int(np.ceil(img.shape[2] / model.vit_patch_size) * model.vit_patch_size),
        )
        paded = torch.zeros(size_im)
        paded[:, : img.shape[1], : img.shape[2]] = img
        img = paded

        # # Move to gpu
        img = img.cuda(non_blocking=True)
        
        # Size for transformers
        w_featmap = img.shape[-2] // model.vit_patch_size
        h_featmap = img.shape[-1] // model.vit_patch_size

        # ------------ GROUND-TRUTH -------------------------------------------
        gt_bbxs, gt_cls = dataset.extract_gt(inp[1], im_name)

        if gt_bbxs is not None:
            # Discard images with no gt annotations
            # Happens only in the case of VOC07 and VOC12
            if gt_bbxs.shape[0] == 0 and no_hards:
                continue

        outputs = model.forward_step(img[None, :, :, :])
        preds = (sigmoid(outputs[0].detach()) > 0.5).float().squeeze().cpu().numpy()

        # get bbox
        pred = get_bbox_from_segmentation_labels(
            segmenter_predictions=preds,
            scales=[model.vit_patch_size, model.vit_patch_size],
            initial_image_size=init_image_size[1:],
        )

        # ------------ Visualizations -------------------------------------------
        # Save the prediction
        preds_dict[im_name] = pred


        # Compare prediction to GT boxes
        ious = bbox_iou(torch.from_numpy(pred), torch.from_numpy(gt_bbxs))

        if torch.any(ious >= 0.5):
            corloc[im_id] = 1
       
        cnt += 1
        if cnt % 50 == 0:
            pbar.set_description(f"Found {int(np.sum(corloc))}/{cnt}")

    # Evaluate
    print(f"corloc: {100*np.sum(corloc)/cnt:.2f} ({int(np.sum(corloc))}/{cnt})")
    result_file = os.path.join(output_dir, 'uod_results.txt')
    with open(result_file, 'w') as f:
        f.write('corloc,%.1f,,\n'%(100*np.sum(corloc)/cnt))
    print('File saved at %s'%result_file)