1
1
import argparse
2
+ import os
2
3
import cv2
3
4
import numpy as np
4
5
import torch
5
6
from torchvision import models
6
- from pytorch_grad_cam import GradCAM , \
7
- HiResCAM , \
8
- ScoreCAM , \
9
- GradCAMPlusPlus , \
10
- AblationCAM , \
11
- XGradCAM , \
12
- EigenCAM , \
13
- EigenGradCAM , \
14
- LayerCAM , \
15
- FullGrad , \
16
- GradCAMElementWise
17
-
18
-
7
+ from pytorch_grad_cam import (
8
+ GradCAM , HiResCAM , ScoreCAM , GradCAMPlusPlus ,
9
+ AblationCAM , XGradCAM , EigenCAM , EigenGradCAM ,
10
+ LayerCAM , FullGrad , GradCAMElementWise
11
+ )
19
12
from pytorch_grad_cam import GuidedBackpropReLUModel
20
- from pytorch_grad_cam .utils .image import show_cam_on_image , \
21
- deprocess_image , \
22
- preprocess_image
13
+ from pytorch_grad_cam .utils .image import (
14
+ show_cam_on_image , deprocess_image , preprocess_image
15
+ )
23
16
from pytorch_grad_cam .utils .model_targets import ClassifierOutputTarget
24
17
25
18
@@ -32,21 +25,24 @@ def get_args():
32
25
type = str ,
33
26
default = './examples/both.png' ,
34
27
help = 'Input image path' )
35
- parser .add_argument ('--aug_smooth ' , action = 'store_true' ,
28
+ parser .add_argument ('--aug-smooth ' , action = 'store_true' ,
36
29
help = 'Apply test time augmentation to smooth the CAM' )
37
30
parser .add_argument (
38
- '--eigen_smooth ' ,
31
+ '--eigen-smooth ' ,
39
32
action = 'store_true' ,
40
- help = 'Reduce noise by taking the first principle componenet '
33
+ help = 'Reduce noise by taking the first principle component '
41
34
'of cam_weights*activations' )
42
35
parser .add_argument ('--method' , type = str , default = 'gradcam' ,
43
- choices = ['gradcam' , 'hirescam' , 'gradcam++' ,
44
- 'scorecam' , 'xgradcam' ,
45
- 'ablationcam' , 'eigencam' ,
46
- 'eigengradcam' , 'layercam' , 'fullgrad' ],
47
- help = 'Can be gradcam/gradcam++/scorecam/xgradcam'
48
- '/ablationcam/eigencam/eigengradcam/layercam' )
49
-
36
+ choices = [
37
+ 'gradcam' , 'hirescam' , 'gradcam++' ,
38
+ 'scorecam' , 'xgradcam' , 'ablationcam' ,
39
+ 'eigencam' , 'eigengradcam' , 'layercam' ,
40
+ 'fullgrad' , 'gradcamelementwise'
41
+ ],
42
+ help = 'CAM method' )
43
+
44
+ parser .add_argument ('--output-dir' , type = str , default = 'output' ,
45
+ help = 'Output directory to save the images' )
50
46
args = parser .parse_args ()
51
47
args .use_cuda = args .use_cuda and torch .cuda .is_available ()
52
48
if args .use_cuda :
@@ -59,25 +55,26 @@ def get_args():
59
55
60
56
if __name__ == '__main__' :
61
57
""" python cam.py -image-path <path_to_image>
62
- Example usage of loading an image, and computing:
58
+ Example usage of loading an image and computing:
63
59
1. CAM
64
60
2. Guided Back Propagation
65
61
3. Combining both
66
62
"""
67
63
68
64
args = get_args ()
69
- methods = \
70
- {"gradcam" : GradCAM ,
71
- "hirescam" : HiResCAM ,
72
- "scorecam" : ScoreCAM ,
73
- "gradcam++" : GradCAMPlusPlus ,
74
- "ablationcam" : AblationCAM ,
75
- "xgradcam" : XGradCAM ,
76
- "eigencam" : EigenCAM ,
77
- "eigengradcam" : EigenGradCAM ,
78
- "layercam" : LayerCAM ,
79
- "fullgrad" : FullGrad ,
80
- "gradcamelementwise" : GradCAMElementWise }
65
+ methods = {
66
+ "gradcam" : GradCAM ,
67
+ "hirescam" : HiResCAM ,
68
+ "scorecam" : ScoreCAM ,
69
+ "gradcam++" : GradCAMPlusPlus ,
70
+ "ablationcam" : AblationCAM ,
71
+ "xgradcam" : XGradCAM ,
72
+ "eigencam" : EigenCAM ,
73
+ "eigengradcam" : EigenGradCAM ,
74
+ "layercam" : LayerCAM ,
75
+ "fullgrad" : FullGrad ,
76
+ "gradcamelementwise" : GradCAMElementWise
77
+ }
81
78
82
79
model = models .resnet50 (pretrained = True )
83
80
@@ -93,6 +90,7 @@ def get_args():
93
90
# You can also try selecting all layers of a certain type, with e.g:
94
91
# from pytorch_grad_cam.utils.find_layers import find_layer_types_recursive
95
92
# find_layer_types_recursive(model, [torch.nn.ReLU])
93
+
96
94
target_layers = [model .layer4 ]
97
95
98
96
rgb_img = cv2 .imread (args .image_path , 1 )[:, :, ::- 1 ]
@@ -115,6 +113,7 @@ def get_args():
115
113
target_layers = target_layers ,
116
114
use_cuda = args .use_cuda ) as cam :
117
115
116
+
118
117
# AblationCAM and ScoreCAM have batched implementations.
119
118
# You can override the internal batch size for faster computation.
120
119
cam .batch_size = 32
@@ -123,12 +122,9 @@ def get_args():
123
122
aug_smooth = args .aug_smooth ,
124
123
eigen_smooth = args .eigen_smooth )
125
124
126
- # Here grayscale_cam has only one image in the batch
127
125
grayscale_cam = grayscale_cam [0 , :]
128
126
129
127
cam_image = show_cam_on_image (rgb_img , grayscale_cam , use_rgb = True )
130
-
131
- # cam_image is RGB encoded whereas "cv2.imwrite" requires BGR encoding.
132
128
cam_image = cv2 .cvtColor (cam_image , cv2 .COLOR_RGB2BGR )
133
129
134
130
gb_model = GuidedBackpropReLUModel (model = model , use_cuda = args .use_cuda )
@@ -138,6 +134,12 @@ def get_args():
138
134
cam_gb = deprocess_image (cam_mask * gb )
139
135
gb = deprocess_image (gb )
140
136
141
- cv2 .imwrite (f'{ args .method } _cam.jpg' , cam_image )
142
- cv2 .imwrite (f'{ args .method } _gb.jpg' , gb )
143
- cv2 .imwrite (f'{ args .method } _cam_gb.jpg' , cam_gb )
137
+ os .makedirs (args .output_dir , exist_ok = True )
138
+
139
+ cam_output_path = os .path .join (args .output_dir , f'{ args .method } _cam.jpg' )
140
+ gb_output_path = os .path .join (args .output_dir , f'{ args .method } _gb.jpg' )
141
+ cam_gb_output_path = os .path .join (args .output_dir , f'{ args .method } _cam_gb.jpg' )
142
+
143
+ cv2 .imwrite (cam_output_path , cam_image )
144
+ cv2 .imwrite (gb_output_path , gb )
145
+ cv2 .imwrite (cam_gb_output_path , cam_gb )
0 commit comments