py-bottom-up-attention
py-bottom-up-attention copied to clipboard
How do I extract the features using an FPN based model?
❓ How to use Detectron2
Questions like:
- How to do extract the features with detectron2 as shown in your demo? I am using this config
I have a pretrained model (trained on custom data) and would like to be able to extract the features of the bounding boxes.
I keep getting
AttributeError: 'StandardROIHeads' object has no attribute '_shared_roi_transform'
I apologized if the answer is obvious, I am very new to object detection.
Thank you!
EDIT
I am confused, I have detectron2 installed. Can I install this onto of my current installation and use it? I ask because it looks like there is a fork of detectron2 in this package which is different from the original detectron2. If I train a model using vanilla detectron2 and install this, can I just load the model weights, and extract the features from there?
I think that you could load the D2 weight into this repo but I am not sure about its validity. Since I have changed the files to support a specific version of faster rcnn in BUTD.
BTW, the modifications are listed in the demo where the model is loaded.
@kevkid You might be facing this issue since FB/detectron2 has moved a lot and there are too many changes there to maintain compatibility. I ported changes from airsplay/py-bottom-up-attention
to most recent detectron2 master over https://github.com/faizanahemad/detectron2 .
You can install that as python -m pip install 'git+https://github.com/faizanahemad/detectron2.git'
.
Follow the demo or it's demo.py file version which does the same as airsplay's demo.
@faizanahemad I wrote this up to extract the features for a detectron2 model. I believe this is correct and I have lots of comments. Let me know if this looks right to you:
class feature_extractor:
'''
Feature Extractor for detectron2
'''
def __init__(self, path = None, output_folder='./output', model = None, pred_thresh = 0.5):
self.pred_thresh = pred_thresh
self.output_folder = output_folder
assert path is not None, 'Path should not be none'
self.path = path
if model == None:
self.model = self._build_detection_model()
else:
assert model == detectron2.engine.defaults.DefaultPredictor, "model should be 'detectron2.engine.defaults.DefaultPredictor'"#
self.model = model
self.model.eval()
def _build_detection_model(self):
cfg = get_cfg()
cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_101_FPN_3x.yaml"))
cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, "model_final.pth")
cfg.SOLVER.IMS_PER_BATCH = 1
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1 # only has one class (pnumonia)
#Just run these lines if you have the trained model im memory
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = self.pred_thresh # set the testing threshold for this model
#build model and return
return DefaultPredictor(cfg)
def _process_feature_extraction(self, img):#step 3
'''
#predictor.model.roi_heads.box_predictor.test_topk_per_image = 1000
#predictor.model.roi_heads.box_predictor.test_nms_thresh = 0.99
#predictor.model.roi_heads.box_predictor.test_score_thresh = 0.0
#pred_boxes = [x.pred_boxes for x in instances]#can use prediction boxes
'''
torch.cuda.empty_cache()
predictor = self.model
with torch.no_grad():#https://detectron2.readthedocs.io/_modules/detectron2/modeling/roi_heads/roi_heads.html : _forward_box()
features = predictor.model.backbone(img.tensor)#have to unsqueeze
proposals, _ = predictor.model.proposal_generator(img, features, None)
results, _ = predictor.model.roi_heads(img, features, proposals, None)
#instances = predictor.model.roi_heads._forward_box(features, proposals)
#get proposed boxes + rois + features + predictions
proposal_boxes = [x.proposal_boxes for x in proposals]
proposal_rois = predictor.model.roi_heads.box_pooler([features[f] for f in predictor.model.roi_heads.in_features], proposal_boxes)
box_features = predictor.model.roi_heads.box_head(proposal_rois)
predictions = predictor.model.roi_heads.box_predictor(box_features)#found here: https://detectron2.readthedocs.io/_modules/detectron2/modeling/roi_heads/roi_heads.html
#WE CAN USE THE PREDICTION CLS TO FIND TOP SCOREING PROPOSAL BOXES!
#pred_instances, losses = predictor.model.roi_heads.box_predictor.inference(predictions, proposals)#something to do with: NMS threshold for prediction results. found: https://github.com/facebookresearch/detectron2/blob/master/detectron2/modeling/roi_heads/fast_rcnn.py#L460
pred_df = pd.DataFrame(predictions[0].softmax(-1).tolist())
pred_classes = pred_df.iloc[:,:-1].apply(np.argmax, axis=1)#get predicted classes
keep = pred_df[pred_df.iloc[:,:-1].apply(lambda x: (x > self.pred_thresh)).values].index.tolist()#list of instances we should keep
#start subsetting
box_features = box_features[keep]
proposal_boxes = proposals[0].proposal_boxes[keep]
pred_classes = pred_classes[keep]
probs = pred_df.iloc[keep, :].apply(lambda x: x[np.argmax(x)], axis=1).tolist()
#['bbox', 'num_boxes', 'objects', 'image_width', 'image_height', 'cls_prob', 'image_id', 'features']
#img.image_sizes[0]#h, w
result = {
'bbox': proposal_boxes.tensor.to('cpu').numpy(),
'num_boxes' : len(proposal_boxes),
'objects' : pred_classes.to_numpy,
#'image_height': img.image_sizes[0][0],
#'image_width': img.image_sizes[0][1],
'cls_prob': np.asarray(probs),#needs to turn into vector!!!!!!!!!!
'features': box_features.to('cpu').detach().numpy()
}
return result
def _save_feature(self, file_name, feature, info):
file_base_name = os.path.basename(file_name)
file_base_name = file_base_name.split(".")[0]
feature["image_id"] = file_base_name
feature['image_height'] = info['height']
feature['image_width'] = info['width']
file_base_name = file_base_name + ".npy"
np.save(os.path.join(self.output_folder, file_base_name), feature)
def extract_features(self):#step 1
torch.cuda.empty_cache()
image_dir = self.path
#print(image_dir)
if type(image_dir) == pd.core.frame.DataFrame:#or pandas.core.frame.DataFrame. Iterate over a dataframe
samples = []
for idx, row in image_dir.iterrows():#get better name
file = row['path']
try:
features, infos = self.get_detectron2_features([file])
self._save_feature(file, features, infos[0])
samples.append(row)
except BaseException:#if no features were found!
print('No features were found!')
pass
df = pd.DataFrame(samples)
#save final csv containing image base names, reports and report locations
df.to_csv(os.path.join(self.output_folder, 'img_infos.csv'))
elif os.path.isfile(image_dir):#if its a single file
features, infos = self.get_detectron2_features([image_dir])
self._save_feature(image_dir, features[0], infos[0])
return features, infos
else:#if its a directory
files = glob.glob(os.path.join(image_dir, "*"))
for idx, file in enumerate(files):
try:
features, infos = self.get_detectron2_features([file])
self._save_feature(file, features, infos[0])
except BaseException:
print('BaseException')
pass
def get_detectron2_features(self, image_paths):#step 2
#we have to PREPROCESS the tensor before partially executing it!
#taken from https://github.com/facebookresearch/detectron2/blob/master/detectron2/engine/defaults.py
predictor = self.model
images = []
image_info = []
for image_path in image_paths:
img = cv2.imread(image_path)
height, width = img.shape[:2]
img = predictor.transform_gen.get_transform(img).apply_image(img)
img = torch.as_tensor(img.astype("float32").transpose(2, 0, 1))
images.append({"image": img, "height": height, "width": width})
image_info.append({"image_id": os.path.basename(image_path), "height": height, "width": width})
imageList = predictor.model.preprocess_image(images)
#returns features and infos
return self._process_feature_extraction(imageList), image_info
Your input should be a DataFrame with the following columns = ['dicom_id', 'path', 'report_path', 'report', 'study_id', 'y'] Should look something like this:
fe = feature_extractor(path=outputs_df, output_folder='/path/to/your/numpy_files.npy')
fe.extract_features()
feature_extractor
@faizanahemad I wrote this up to extract the features for a detectron2 model. I believe this is correct and I have lots of comments. Let me know if this looks right to you:
Hi @kevkid , do not find feature_extractor
let alone the "lots of comments" (from github or from current LXMERT repo). Basically, I am interested in using a smaller backbone and hence I am interested in weights conversion (for example, resnet18
instead of resnet101
). I also follow #6, #16 .
❓ How to use Detectron2
Questions like:
- How to do extract the features with detectron2 as shown in your demo? I am using this config I have a pretrained model (trained on custom data) and would like to be able to extract the features of the bounding boxes. I keep getting
AttributeError: 'StandardROIHeads' object has no attribute '_shared_roi_transform'
I apologized if the answer is obvious, I am very new to object detection.
Thank you!
EDIT
I am confused, I have detectron2 installed. Can I install this onto of my current installation and use it? I ask because it looks like there is a fork of detectron2 in this package which is different from the original detectron2. If I train a model using vanilla detectron2 and install this, can I just load the model weights, and extract the features from there?
Hi @kevkid, your mask_rcnn_R_101_FPN_3x.yaml and @ThierryDeruyttere's faster_rcnn_R_101_C4_attr_caffemaxpool.yaml in #16 are starting point for my goal (repeatly, my goal is I am using a smaller backbone (for example, resnet18
instead of resnet101
).
❓ How to use Detectron2
Questions like:
- How to do extract the features with detectron2 as shown in your demo? I am using this config I have a pretrained model (trained on custom data) and would like to be able to extract the features of the bounding boxes. I keep getting
AttributeError: 'StandardROIHeads' object has no attribute '_shared_roi_transform'
I apologized if the answer is obvious, I am very new to object detection.
Thank you!
EDIT
I am confused, I have detectron2 installed. Can I install this onto of my current installation and use it? I ask because it looks like there is a fork of detectron2 in this package which is different from the original detectron2. If I train a model using vanilla detectron2 and install this, can I just load the model weights, and extract the features from there?
Hi @kevkid , after referring to detectron2_mscoco_proposal_maxnms.py and coming up with code in #6 , I am looking into your feature_extractor
and think cfg.MODEL.WEIGHTS = 'R-50.pkl'
together with
cfg.merge_from_file('../configs/COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml')
or cfg.merge_from_file('../configs/COCO-Detection/faster_rcnn_R_50_DC5_1x.yaml')
also result in
AttributeError: 'StandardROIHeads' object has no attribute '_shared_roi_transform'
while cfg.MODEL.WEIGHTS = 'R-50.pkl'
together with
cfg.merge_from_file('../configs/COCO-Detection/faster_rcnn_R_50_C4_1x.yaml')
or cfg.merge_from_file('../configs/COCO-Detection/faster_rcnn_R_50_C4_3x.yaml')
or cfg.merge_from_file('../configs/COCO-Detection/faster_rcnn_R_50_FPN_3x.yaml')
result in
/github/py-bottom-up-attention/detectron2/layers/roi_align.py in forward(ctx, input, roi, output_size, spatial_scale, sampling_ratio, aligned)
18 ctx.aligned = aligned
19 output = _C.roi_align_forward(
---> 20 input, roi, spatial_scale, output_size[0], output_size[1], sampling_ratio, aligned
21 )
22 return output
RuntimeError: Not compiled with GPU support (ROIAlign_forward at /github/py-bottom-up-attention/detectron2/layers/csrc/ROIAlign/ROIAlign.h:73)
frame #0: c10::Error::Error(c10::SourceLocation, std::string const&) + 0x33 (0x7fb5494f2193 in /opt/conda/lib/python3.6/site-packages/torch/lib/libc10.so)
frame #1: detectron2::ROIAlign_forward(at::Tensor const&, at::Tensor const&, float, int, int, int, bool) + 0x171 (0x7fb54867df61 in /github/py-bottom-up-attention/detectron2/_C.cpython-36m-x86_64-linux-gnu.so)
frame #2: <unknown function> + 0x1faea (0x7fb54868daea in /github/py-bottom-up-attention/detectron2/_C.cpython-36m-x86_64-linux-gnu.so)
frame #3: <unknown function> + 0x1aba0 (0x7fb548688ba0 in /github/py-bottom-up-attention/detectron2/_C.cpython-36m-x86_64-linux-gnu.so)
frame #4: _PyCFunction_FastCallDict + 0x154 (0x5608c725ac54 in /opt/conda/bin/python)
frame #5: <unknown function> + 0x199abc (0x5608c72e2abc in /opt/conda/bin/python)
frame #6: _PyEval_EvalFrameDefault + 0x30a (0x5608c730575a in /opt/conda/bin/python)
frame #7: PyEval_EvalCodeEx + 0x329 (0x5608c72dd9b9 in /opt/conda/bin/python)
frame #8: <unknown function> + 0x1957d4 (0x5608c72de7d4 in /opt/conda/bin/python)
frame #9: PyObject_Call + 0x3e (0x5608c725aa5e in /opt/conda/bin/python)
frame #10: THPFunction_apply(_object*, _object*) + 0xa8f (0x7fb59454c82f in /opt/conda/lib/python3.6/site-packages/torch/lib/libtorch_python.so)
frame #11: _PyCFunction_FastCallDict + 0x91 (0x5608c725ab91 in /opt/conda/bin/python)
frame #12: <unknown function> + 0x199abc (0x5608c72e2abc in /opt/conda/bin/python)
frame #13: _PyEval_EvalFrameDefault + 0x30a (0x5608c730575a in /opt/conda/bin/python)
frame #14: _PyFunction_FastCallDict + 0x11b (0x5608c72dd2db in /opt/conda/bin/python)
frame #15: _PyObject_FastCallDict + 0x26f (0x5608c725b01f in /opt/conda/bin/python)
frame #16: _PyObject_Call_Prepend + 0x63 (0x5608c725faa3 in /opt/conda/bin/python)
frame #17: PyObject_Call + 0x3e (0x5608c725aa5e in /opt/conda/bin/python)
frame #18: _PyEval_EvalFrameDefault + 0x19e7 (0x5608c7306e37 in /opt/conda/bin/python)
frame #19: <unknown function> + 0x192e66 (0x5608c72dbe66 in /opt/conda/bin/python)
frame #20: _PyFunction_FastCallDict + 0x1be (0x5608c72dd37e in /opt/conda/bin/python)
frame #21: _PyObject_FastCallDict + 0x26f (0x5608c725b01f in /opt/conda/bin/python)
frame #22: _PyObject_Call_Prepend + 0x63 (0x5608c725faa3 in /opt/conda/bin/python)
frame #23: PyObject_Call + 0x3e (0x5608c725aa5e in /opt/conda/bin/python)
frame #24: <unknown function> + 0x16b371 (0x5608c72b4371 in /opt/conda/bin/python)
frame #25: _PyObject_FastCallDict + 0x8b (0x5608c725ae3b in /opt/conda/bin/python)
frame #26: <unknown function> + 0x199c0e (0x5608c72e2c0e in /opt/conda/bin/python)
frame #27: _PyEval_EvalFrameDefault + 0x30a (0x5608c730575a in /opt/conda/bin/python)
frame #28: _PyFunction_FastCallDict + 0x11b (0x5608c72dd2db in /opt/conda/bin/python)
frame #29: _PyObject_FastCallDict + 0x26f (0x5608c725b01f in /opt/conda/bin/python)
frame #30: _PyObject_Call_Prepend + 0x63 (0x5608c725faa3 in /opt/conda/bin/python)
frame #31: PyObject_Call + 0x3e (0x5608c725aa5e in /opt/conda/bin/python)
frame #32: _PyEval_EvalFrameDefault + 0x19e7 (0x5608c7306e37 in /opt/conda/bin/python)
frame #33: <unknown function> + 0x192e66 (0x5608c72dbe66 in /opt/conda/bin/python)
frame #34: _PyFunction_FastCallDict + 0x1be (0x5608c72dd37e in /opt/conda/bin/python)
frame #35: _PyObject_FastCallDict + 0x26f (0x5608c725b01f in /opt/conda/bin/python)
frame #36: _PyObject_Call_Prepend + 0x63 (0x5608c725faa3 in /opt/conda/bin/python)
frame #37: PyObject_Call + 0x3e (0x5608c725aa5e in /opt/conda/bin/python)
frame #38: <unknown function> + 0x16b371 (0x5608c72b4371 in /opt/conda/bin/python)
frame #39: _PyObject_FastCallDict + 0x8b (0x5608c725ae3b in /opt/conda/bin/python)
frame #40: <unknown function> + 0x199c0e (0x5608c72e2c0e in /opt/conda/bin/python)
frame #41: _PyEval_EvalFrameDefault + 0x30a (0x5608c730575a in /opt/conda/bin/python)
frame #42: <unknown function> + 0x193c5b (0x5608c72dcc5b in /opt/conda/bin/python)
frame #43: <unknown function> + 0x199b95 (0x5608c72e2b95 in /opt/conda/bin/python)
frame #44: _PyEval_EvalFrameDefault + 0x30a (0x5608c730575a in /opt/conda/bin/python)
frame #45: <unknown function> + 0x19329e (0x5608c72dc29e in /opt/conda/bin/python)
frame #46: <unknown function> + 0x193ed6 (0x5608c72dced6 in /opt/conda/bin/python)
frame #47: <unknown function> + 0x199b95 (0x5608c72e2b95 in /opt/conda/bin/python)
frame #48: _PyEval_EvalFrameDefault + 0x30a (0x5608c730575a in /opt/conda/bin/python)
frame #49: <unknown function> + 0x193c5b (0x5608c72dcc5b in /opt/conda/bin/python)
frame #50: <unknown function> + 0x199b95 (0x5608c72e2b95 in /opt/conda/bin/python)
frame #51: _PyEval_EvalFrameDefault + 0x30a (0x5608c730575a in /opt/conda/bin/python)
frame #52: PyEval_EvalCodeEx + 0x329 (0x5608c72dd9b9 in /opt/conda/bin/python)
frame #53: PyEval_EvalCode + 0x1c (0x5608c72de75c in /opt/conda/bin/python)
frame #54: <unknown function> + 0x1ba167 (0x5608c7303167 in /opt/conda/bin/python)
frame #55: _PyCFunction_FastCallDict + 0x91 (0x5608c725ab91 in /opt/conda/bin/python)
frame #56: <unknown function> + 0x199abc (0x5608c72e2abc in /opt/conda/bin/python)
frame #57: _PyEval_EvalFrameDefault + 0x30a (0x5608c730575a in /opt/conda/bin/python)
frame #58: _PyGen_Send + 0x256 (0x5608c72e5be6 in /opt/conda/bin/python)
frame #59: _PyEval_EvalFrameDefault + 0x144f (0x5608c730689f in /opt/conda/bin/python)
frame #60: _PyGen_Send + 0x256 (0x5608c72e5be6 in /opt/conda/bin/python)
frame #61: _PyEval_EvalFrameDefault + 0x144f (0x5608c730689f in /opt/conda/bin/python)
frame #62: _PyGen_Send + 0x256 (0x5608c72e5be6 in /opt/conda/bin/python)
frame #63: _PyCFunction_FastCallDict + 0x115 (0x5608c725ac15 in /opt/conda/bin/python)
For RuntimeError: Not compiled with GPU support
, I verified via
python -c 'import torch; from torch.utils.cpp_extension import CUDA_HOME; print(torch.cuda.is_available(), CUDA_HOME)'
in https://detectron2.readthedocs.io/tutorials/install.html#common-installation-issues suggested by detectron2 issue#1406 and it outputs True /usr/local/cuda
.
@faizanahemad I wrote this up to extract the features for a detectron2 model. I believe this is correct and I have lots of comments. Let me know if this looks right to you:
class feature_extractor: ''' Feature Extractor for detectron2 ''' def __init__(self, path = None, output_folder='./output', model = None, pred_thresh = 0.5): self.pred_thresh = pred_thresh self.output_folder = output_folder assert path is not None, 'Path should not be none' self.path = path if model == None: self.model = self._build_detection_model() else: assert model == detectron2.engine.defaults.DefaultPredictor, "model should be 'detectron2.engine.defaults.DefaultPredictor'"# self.model = model self.model.eval() def _build_detection_model(self): cfg = get_cfg() cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_101_FPN_3x.yaml")) cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, "model_final.pth") cfg.SOLVER.IMS_PER_BATCH = 1 cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1 # only has one class (pnumonia) #Just run these lines if you have the trained model im memory cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = self.pred_thresh # set the testing threshold for this model #build model and return return DefaultPredictor(cfg) def _process_feature_extraction(self, img):#step 3 ''' #predictor.model.roi_heads.box_predictor.test_topk_per_image = 1000 #predictor.model.roi_heads.box_predictor.test_nms_thresh = 0.99 #predictor.model.roi_heads.box_predictor.test_score_thresh = 0.0 #pred_boxes = [x.pred_boxes for x in instances]#can use prediction boxes ''' torch.cuda.empty_cache() predictor = self.model with torch.no_grad():#https://detectron2.readthedocs.io/_modules/detectron2/modeling/roi_heads/roi_heads.html : _forward_box() features = predictor.model.backbone(img.tensor)#have to unsqueeze proposals, _ = predictor.model.proposal_generator(img, features, None) results, _ = predictor.model.roi_heads(img, features, proposals, None) #instances = predictor.model.roi_heads._forward_box(features, proposals) #get proposed boxes + rois + features + predictions proposal_boxes = [x.proposal_boxes for x in proposals] proposal_rois = predictor.model.roi_heads.box_pooler([features[f] for f in predictor.model.roi_heads.in_features], proposal_boxes) box_features = predictor.model.roi_heads.box_head(proposal_rois) predictions = predictor.model.roi_heads.box_predictor(box_features)#found here: https://detectron2.readthedocs.io/_modules/detectron2/modeling/roi_heads/roi_heads.html #WE CAN USE THE PREDICTION CLS TO FIND TOP SCOREING PROPOSAL BOXES! #pred_instances, losses = predictor.model.roi_heads.box_predictor.inference(predictions, proposals)#something to do with: NMS threshold for prediction results. found: https://github.com/facebookresearch/detectron2/blob/master/detectron2/modeling/roi_heads/fast_rcnn.py#L460 pred_df = pd.DataFrame(predictions[0].softmax(-1).tolist()) pred_classes = pred_df.iloc[:,:-1].apply(np.argmax, axis=1)#get predicted classes keep = pred_df[pred_df.iloc[:,:-1].apply(lambda x: (x > self.pred_thresh)).values].index.tolist()#list of instances we should keep #start subsetting box_features = box_features[keep] proposal_boxes = proposals[0].proposal_boxes[keep] pred_classes = pred_classes[keep] probs = pred_df.iloc[keep, :].apply(lambda x: x[np.argmax(x)], axis=1).tolist() #['bbox', 'num_boxes', 'objects', 'image_width', 'image_height', 'cls_prob', 'image_id', 'features'] #img.image_sizes[0]#h, w result = { 'bbox': proposal_boxes.tensor.to('cpu').numpy(), 'num_boxes' : len(proposal_boxes), 'objects' : pred_classes.to_numpy, #'image_height': img.image_sizes[0][0], #'image_width': img.image_sizes[0][1], 'cls_prob': np.asarray(probs),#needs to turn into vector!!!!!!!!!! 'features': box_features.to('cpu').detach().numpy() } return result def _save_feature(self, file_name, feature, info): file_base_name = os.path.basename(file_name) file_base_name = file_base_name.split(".")[0] feature["image_id"] = file_base_name feature['image_height'] = info['height'] feature['image_width'] = info['width'] file_base_name = file_base_name + ".npy" np.save(os.path.join(self.output_folder, file_base_name), feature) def extract_features(self):#step 1 torch.cuda.empty_cache() image_dir = self.path #print(image_dir) if type(image_dir) == pd.core.frame.DataFrame:#or pandas.core.frame.DataFrame. Iterate over a dataframe samples = [] for idx, row in image_dir.iterrows():#get better name file = row['path'] try: features, infos = self.get_detectron2_features([file]) self._save_feature(file, features, infos[0]) samples.append(row) except BaseException:#if no features were found! print('No features were found!') pass df = pd.DataFrame(samples) #save final csv containing image base names, reports and report locations df.to_csv(os.path.join(self.output_folder, 'img_infos.csv')) elif os.path.isfile(image_dir):#if its a single file features, infos = self.get_detectron2_features([image_dir]) self._save_feature(image_dir, features[0], infos[0]) return features, infos else:#if its a directory files = glob.glob(os.path.join(image_dir, "*")) for idx, file in enumerate(files): try: features, infos = self.get_detectron2_features([file]) self._save_feature(file, features, infos[0]) except BaseException: print('BaseException') pass def get_detectron2_features(self, image_paths):#step 2 #we have to PREPROCESS the tensor before partially executing it! #taken from https://github.com/facebookresearch/detectron2/blob/master/detectron2/engine/defaults.py predictor = self.model images = [] image_info = [] for image_path in image_paths: img = cv2.imread(image_path) height, width = img.shape[:2] img = predictor.transform_gen.get_transform(img).apply_image(img) img = torch.as_tensor(img.astype("float32").transpose(2, 0, 1)) images.append({"image": img, "height": height, "width": width}) image_info.append({"image_id": os.path.basename(image_path), "height": height, "width": width}) imageList = predictor.model.preprocess_image(images) #returns features and infos return self._process_feature_extraction(imageList), image_info
Your input should be a DataFrame with the following columns = ['dicom_id', 'path', 'report_path', 'report', 'study_id', 'y'] Should look something like this:
fe = feature_extractor(path=outputs_df, output_folder='/path/to/your/numpy_files.npy') fe.extract_features()
@kevkid I also get this problem: AttributeError: 'StandardROIHeads' object has no attribute '_shared_roi_transform'
does above code work ?