def main(args):

    # Load the synset words
    file_name = 'synset_words.txt'
    classes = list()
    with open(file_name) as class_file:
        for line in class_file:
            classes.append(line.strip().split(' ', 1)[1].split(', ',
                                                               1)[0].replace(
                                                                   ' ', '_'))

    print('Loading a model...')
    model = torchvision.models.resnet152(pretrained=True)
    transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225])
    ])

    print('\nGrad-CAM')
    gcam = GradCAM(model=model,
                   target_layer='layer4.2',
                   n_class=1000,
                   cuda=args.cuda)
    gcam.load_image(args.image, transform)
    gcam.forward()

    for i in range(0, 5):
        gcam.backward(idx=gcam.idx[i])
        cls_name = classes[gcam.idx[i]]
        output = gcam.generate()
        print('\t{:.5f}\t{}'.format(gcam.prob[i], cls_name))
        gcam.save('results/{}_gcam.png'.format(cls_name), output)

    print('\nBackpropagation')
    bp = BackPropagation(model=model,
                         target_layer='conv1',
                         n_class=1000,
                         cuda=args.cuda)
    bp.load_image(args.image, transform)
    bp.forward()

    for i in range(0, 5):
        bp.backward(idx=bp.idx[i])
        cls_name = classes[bp.idx[i]]
        output = bp.generate()
        print('\t{:.5f}\t{}'.format(bp.prob[i], cls_name))
        bp.save('results/{}_bp.png'.format(cls_name), output)

    print('\nGuided Backpropagation')
    gbp = GuidedBackPropagation(model=model,
                                target_layer='conv1',
                                n_class=1000,
                                cuda=args.cuda)
    gbp.load_image(args.image, transform)
    gbp.forward()

    for i in range(0, 5):
        cls_idx = gcam.idx[i]
        cls_name = classes[cls_idx]

        gcam.backward(idx=cls_idx)
        output_gcam = gcam.generate()

        gbp.backward(idx=cls_idx)
        output_gbp = gbp.generate()

        output_gcam -= output_gcam.min()
        output_gcam /= output_gcam.max()
        output_gcam = cv2.resize(output_gcam, (224, 224))
        output_gcam = cv2.cvtColor(output_gcam, cv2.COLOR_GRAY2BGR)

        output = output_gbp * output_gcam

        print('\t{:.5f}\t{}'.format(gbp.prob[i], cls_name))
        gbp.save('results/{}_gbp.png'.format(cls_name), output_gbp)
        gbp.save('results/{}_ggcam.png'.format(cls_name), output)
Exemple #2
0
def gradCAM():
    # Chap 2 : Train Network
    print('\n[Chapter 2] : Operate gradCAM with trained network')

    # Phase 1 : Model Upload
    print('\n[Phase 1] : Model Weight Upload')
    use_gpu = torch.cuda.is_available()

    # upload labels
    data_dir = cf.test_dir
    trainset_dir = cf.data_base.split("/")[-1] + os.sep

    dsets = datasets.ImageFolder(data_dir, None)
    H = datasets.ImageFolder(cf.aug_base + '/train/')
    dset_classes = H.classes

    def softmax(x):
        return np.exp(x) / np.sum(np.exp(x), axis=0)
        # return np.exp(x) / np.sum(np.exp(x), axis=1)


    def getNetwork(opts):
        if (opts.net_type == 'alexnet'):
            file_name = 'alexnet'
        elif (opts.net_type == 'vggnet'):
            file_name = 'vgg-%s' % (opts.depth)
        elif (opts.net_type == 'resnet'):
            file_name = 'resnet-%s' % (opts.depth)
        else:
            print('[Error]: Network should be either [alexnet / vgget / resnet]')
            sys.exit(1)

        return file_name

    def random_crop(image, dim):
        if len(image.shape):
            W, H, D = image.shape
            w, h, d = dim
        else:
            W, H = image.shape
            w, h = dim[0], dim[1]

        left, top = np.random.randint(W - w + 1), np.random.randint(H - h + 1)
        return image[left:left + w, top:top + h], left, top

    # uploading the model
    print("| Loading checkpoint model for grad-CAM...")
    assert os.path.isdir('./path'), '[Error]: No checkpoint directory found!'
    assert os.path.isdir('./path/' + trainset_dir), '[Error]: There is no model weight to upload!'
    file_name = getNetwork(opts)
    checkpoint = torch.load('./path/' + trainset_dir + file_name + '.t7')
    model = checkpoint['model']

    if use_gpu:
        model.cuda()
        cudnn.benchmark = True

    model.eval()

    sample_input = Variable(torch.randn(1, 3, 224, 224), volatile=False)
    if use_gpu:
        sampe_input = sample_input.cuda()

    def is_image(f):
        return f.endswith(".png") or f.endswith(".jpg")

    test_transform = transforms.Compose([
        transforms.Resize(224),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(cf.mean, cf.std)
    ])

    """
    #@ Code for inference test

    img = Image.open(cf.image_path)
    if test_transform is not None:
        img = test_transform(img)
    inputs = img
    inputs = Variable(inputs, volatile=False, requires_grad=True)

    if use_gpu:
        inputs = inputs.cuda()
    inputs = inputs.view(1, inputs.size(0), inputs.size(1), inputs.size(2))

    outputs = model(inputs)
    softmax_res = softmax(outputs.data.cpu().numpy()[0])

    index,score = max(enumerate(softmax_res), key=operator.itemgetter(1))

    print('| Uploading %s' %(cf.image_path.split("/")[-1]))
    print('| prediction = ' + dset_classes[index])
    """

    # @ Code for extracting a grad-CAM region for a given class
    gcam = GradCAM(list(model._modules.items())[0][1],
                   cuda=use_gpu)  # model=model._modules.items()[0][1], cuda=use_gpu)
    gbp = GuidedBackPropagation(model=list(model._modules.items())[0][1], cuda=use_gpu)

    # print(dset_classes)
    WBC_id = 5  # BHX class
    print("Checking Activated Regions for " + dset_classes[WBC_id] + "...")

    fileList = os.listdir('./samples/')
    i = 1
    for f in fileList:
        file_name = './samples/' + f
        print("Opening " + file_name + "...")

        original_image = cv2.imread(file_name)
        resize_ratio = 224. / min(original_image.shape[0:2])
        resized = cv2.resize(original_image, (0, 0), fx=resize_ratio, fy=resize_ratio)
        cropped, left, top = random_crop(resized, (224, 224, 3))
        print(cropped.size)
        if test_transform is not None:
            img = test_transform(Image.fromarray(cropped, mode='RGB'))
        # center_cropped = original_image[16:240, 16:240, :]
        # expand the image based on the short side

        inputs = img
        inputs = Variable(inputs, requires_grad=True)

        if use_gpu:
            inputs = inputs.cuda()
        inputs = inputs.view(1, inputs.size(0), inputs.size(1), inputs.size(2))

        probs, idx = gcam.forward(inputs)
        # probs, idx = gbp.forward(inputs)

        # Grad-CAM
        gcam.backward(idx=WBC_id)
        if opts.depth == 18:
            output = gcam.generate(target_layer='layer4.1')
        else:
            output = gcam.generate(target_layer='layer4.2')  # a module name to be visualized (required)

        # Guided Back Propagation
        # gbp.backward(idx=WBC_id)
        # feature = gbp.generate(target_layer='conv1')

        # Guided Grad-CAM
        # output = np.multiply(feature, region)

        gcam.save('./results/%s.png' % str(i), output, cropped)
        cv2.imwrite('./results/map%s.png' % str(i), cropped)

        for j in range(3):
            print('\t{:5f}\t{}\n'.format(probs[j], dset_classes[idx[j]]))

        i += 1

    """