scene graph generation benchmark中faster rcnn的识别结果的下载使用方法
但是像obj_scores这样的变量,我虽然很相信这是Faster R-CNN 模型对每个检测到的对象的置信度分数(即这些分数表示模型对每个检测结果的置信程度,数值越高表示模型越确信该检测结果是正确的),但我不知道如何去用。其他变量都已经解释的很清楚了,大家按照ind_to_classes那些变量把对应的序号替换成英文单词即可(若不懂,给我留言,我有空再回来解释)这个文件里的意思是,faster
scene graph generation benchmark中faster rcnn的识别结果的下载使用方法
下载faster rcnn的识别结果
众所周知,scene graph generation benchmark官网的实现方法是一种两阶段的生成。即先使用faster rcnn识别图片中所存在的物体以及物体的bbox,再去判断相对应的物体之间的关系。
(当然我这样说是有问题的,因为sgg是有三个任务,在sgdet任务中,才是真正的两阶段识别,其他的任务会利用gt的bbox或label)
既然sgdet需要利用到faster rcnn的识别结果,那大家可以按如下方式下载。
在Scene-Graph-Benchmark.pytorch/maskrcnn_benchmark/data/datasets/evaluation/vg/vg_eval.py
这个文件的46行到55行:
groundtruths = []
for image_id, prediction in enumerate(predictions):
img_info = dataset.get_img_info(image_id)
image_width = img_info["width"]
image_height = img_info["height"]
# recover original size which is before transform
predictions[image_id] = prediction.resize((image_width, image_height))
gt = dataset.get_groundtruth(image_id, evaluation=True)
groundtruths.append(gt)
上面这部分代码,实际上出现了三个很重要的变量,分别是groundtruths
,dataset,predictions
。其中groundtruths是从dataset(也就是数据集提取的(通过get_groundtruth))函数
当我们运行sgdet模式的命令的时候,我们的predictions里就保存了相关faster rcnn的运行结果,所以我们在这里下方加入这样一个函数:
save_output_pred(output_folder, groundtruths, predictions, dataset)
这个函数内容如下
def save_output_pred(output_folder, groundtruths, predictions, dataset):
if output_folder:
visual_info = []
total_images = len(groundtruths) # 总共处理了多少张图片
for image_id, (groundtruth, prediction) in enumerate(zip(groundtruths, predictions)):
# 文件保存路径
img_file = os.path.abspath(dataset.filenames[image_id])
# gt相关内容
gt_rels = groundtruth.get_field('relation_tuple').long().detach().cpu().numpy().tolist()
gt_boxes = groundtruth.convert('xyxy').bbox.detach().cpu().numpy().tolist() # (#gt_objs, 4)
gt_classes = groundtruth.get_field('labels').long().detach().cpu().numpy().tolist() # (#gt_objs, )
# pred的relation相关内容:
pred_rel_inds = prediction.get_field('rel_pair_idxs').long().detach().cpu().numpy().tolist() # (#pred_rels, 2)
rel_scores = prediction.get_field('pred_rel_scores').detach().cpu().numpy().tolist() # (#pred_rels, num_pred_class)
# pred的bbox相关内容
pred_boxes = prediction.convert('xyxy').bbox.detach().cpu().numpy().tolist() # (#pred_objs, 4)
# 如果是xywh的话,可以这么写:prediction.convert('xywh').bbox.detach().cpu().numpy()
pred_classes = prediction.get_field('pred_labels').long().detach().cpu().numpy().tolist() # (#pred_objs, )
obj_scores = prediction.get_field('pred_scores').detach().cpu().numpy().tolist() # (#pred_objs, )
# 没法保存序号和关系,序号和也没有关系,
# pred_rel_inds我感觉和recall值会很相关。可能是每个类别计算出的正确分数,或每个类别计算出的recall相关分数
visual_info.append({
'image_id' : image_id,
'img_file' : img_file,
'gt_rels' : gt_rels,
'gt_boxes' : gt_boxes,
'gt_classes' : gt_classes,
'pred_rel_inds' : pred_rel_inds,
'rel_scores' : rel_scores,
'pred_boxes' : pred_boxes,
'pred_classes' : pred_classes,
'obj_scores' : obj_scores
})
# 打印已处理的图片数量
if (image_id + 1) % 1000 == 0:
print(f"Processed {image_id + 1}/{total_images} images")
with open(os.path.join(output_folder, "gt_and_pred_info.json"), "w") as f:
json.dump(visual_info, f)
这样我们就能把groundtruth
和predictions
都保存下来做进一步的处理。
但是要注意就是:
如果下面这些都保存下来会很大很大,所以我把pred_rel_inds 和rel_scores注释掉了,因为我暂时用不到
visual_info.append({
'image_id' : image_id,
'img_file' : img_file,
'gt_rels' : gt_rels,
'gt_boxes' : gt_boxes,
'gt_classes' : gt_classes,
# 'pred_rel_inds' : pred_rel_inds,
# 'rel_scores' : rel_scores,
'pred_boxes' : pred_boxes,
'pred_classes' : pred_classes,
'obj_scores' : obj_scores
})
我现在已经把相关的json文件保存下来了,里面的变量如下所示
大家随用随取。
链接: https://pan.baidu.com/s/1KkEabUaskF8fDrWyx4iF0A 提取码: qz2p 复制这段内容后打开百度网盘手机App,操作更方便哦
–来自百度网盘超级会员v8的分享
这个文件的使用方法
其他变量都已经解释的很清楚了,大家按照ind_to_classes那些变量把对应的序号替换成英文单词即可(若不懂,给我留言,我有空再回来解释)
但是像obj_scores这样的变量,我虽然很相信这是Faster R-CNN 模型对每个检测到的对象的置信度分数(即这些分数表示模型对每个检测结果的置信程度,数值越高表示模型越确信该检测结果是正确的),但我不知道如何去用。
就是,我知道这个项目里,像obj_score这个变量,大概率会用于以下几个方面:
- 过滤低置信度的检测结果:通过设定一个置信度阈值,只保留置信度高于该阈值的检测结果,从而减少误检。
- 排序检测结果:根据置信度分数对检测结果进行排序,优先处理置信度高的结果。
- 评估模型性能:在评估模型性能时,obj_scores 可以用于计算平均精度(AP)等指标。
但我不是十分确定。所以我的处理方法如下,希望能对大家有所参考:
我使用vscode全局搜索了obj_scores,发现其在:
-
maskrcnn_benchmark/data/datasets/evaluation/vg/sgg_eval.py里有应用,其函数如下:
def calculate_recall(self, global_container, local_container, mode): pred_rel_inds = local_container['pred_rel_inds'] rel_scores = local_container['rel_scores'] gt_rels = local_container['gt_rels'] gt_classes = local_container['gt_classes'] gt_boxes = local_container['gt_boxes'] pred_classes = local_container['pred_classes'] pred_boxes = local_container['pred_boxes'] obj_scores = local_container['obj_scores'] iou_thres = global_container['iou_thres'] pred_rels = np.column_stack((pred_rel_inds, 1+rel_scores[:,1:].argmax(1))) pred_scores = rel_scores[:,1:].max(1) gt_triplets, gt_triplet_boxes, _ = _triplet(gt_rels, gt_classes, gt_boxes) local_container['gt_triplets'] = gt_triplets local_container['gt_triplet_boxes'] = gt_triplet_boxes pred_triplets, pred_triplet_boxes, pred_triplet_scores = _triplet( pred_rels, pred_classes, pred_boxes, pred_scores, obj_scores) # Compute recall. It's most efficient to match once and then do recall after pred_to_gt = _compute_pred_matches( gt_triplets, pred_triplets, gt_triplet_boxes, pred_triplet_boxes, iou_thres, phrdet=mode=='phrdet', ) local_container['pred_to_gt'] = pred_to_gt for k in self.result_dict[mode + '_recall']: # the following code are copied from Neural-MOTIFS match = reduce(np.union1d, pred_to_gt[:k]) rec_i = float(len(match)) / float(gt_rels.shape[0]) self.result_dict[mode + '_recall'][k].append(rec_i) return local_container
这个函数的作用是把obj_scores保存下来,最终把pred的三元组送去和groundtruths去进行评估。后续可以观察一下上述代码
-
maskrcnn_benchmark/image_retrieval/preprocessing.py 这个文件里也应用了,其内容如下:
def generate_detect_sg(det_result, det_info, valid_ids, img_coco_map, obj_thres = 0.1):
num_img = len(det_info)
groundtruths = det_result['groundtruths']
predictions = det_result['predictions']
assert len(groundtruths) == num_img
assert len(predictions) == num_img
output = {}
for i in range(num_img):
# load detect result
image_id = det_info[i]['img_file'].split('/')[-1].split('.')[0]
if int(image_id) not in valid_ids:
continue
all_obj_labels = predictions[i].get_field('pred_labels')
all_obj_scores = predictions[i].get_field('pred_scores')
all_rel_pairs = predictions[i].get_field('rel_pair_idxs')
all_rel_prob = predictions[i].get_field('pred_rel_scores')
all_rel_scores, all_rel_labels = all_rel_prob.max(-1)
# filter objects and relationships
all_obj_scores[all_obj_scores < obj_thres] = 0.0
obj_mask = all_obj_scores >= obj_thres
triplet_score = all_obj_scores[all_rel_pairs[:, 0]] * all_obj_scores[all_rel_pairs[:, 1]] * all_rel_scores
rel_mask = ((all_rel_labels > 0) + (triplet_score > 0)) > 0
# generate filterred result
num_obj = obj_mask.shape[0]
num_rel = rel_mask.shape[0]
rel_matrix = torch.zeros((num_obj, num_obj))
for k in range(num_rel):
if rel_mask[k]:
rel_matrix[int(all_rel_pairs[k, 0]), int(all_rel_pairs[k, 1])] = all_rel_labels[k]
rel_matrix = rel_matrix[obj_mask][:, obj_mask].long()
filter_obj = all_obj_labels[obj_mask]
filter_pair = torch.nonzero(rel_matrix > 0)
filter_rel = rel_matrix[filter_pair[:, 0], filter_pair[:, 1]]
# generate labels
pred_objs = [vg_dict['idx_to_label'][str(i)] for i in filter_obj.tolist()]
pred_rels = [[i[0], i[1], cap_graph['idx_to_meta_predicate'][str(j)]] for i, j in zip(filter_pair.tolist(), filter_rel.tolist())]
coco_id = img_coco_map[int(image_id)]
output[str(coco_id)] = [{'entities' : pred_objs, 'relations' : pred_rels}, ]
return output
这个文件里的意思是,faster rcnn的识别结果,也就是obj_scores物体打分,要大于0.1才会被保存下来。
所以我最终确定了obj_scores确实在这个项目里按如下思想应用:
- 过滤低置信度的检测结果:通过设定一个置信度阈值,只保留置信度高于该阈值的检测结果,从而减少误检。
- 排序检测结果:根据置信度分数对检测结果进行排序,优先处理置信度高的结果(这个待定)。
- 评估模型性能:在评估模型性能时,obj_scores 可以用于计算平均精度(AP)等指标。
希望对大家有所帮助
再次更新了一个新的文件,把groundtruth包含的图片中的每个物体的序号换成了对应的英文单词,把predications包含的图片中的每个物体的序号换成了对应的英文单词。
替换方法如下:
- gt_rels的文件结构是
【物体1在当前图片bbox中的序号,物体2在当前图片bbox中的序号,关系的类别序号】
- 先将其替换成格式如下:
【物体1在当前图片bbox中的序号,关系的动词类别序号,物体2在当前图片bbox中的序号】
- 再将其替换如下:
【物体1的名词类别序号,关系的动词类别序号,物体2的名词类别序号】
- 比如图片1的
gt_classes
的值如下[38, 65, 85, 99, 135, 136, 145, 146, 149]
,其保存的是bbox对应的名词类别序号
。 - 比如物体1是
第3个bbox
,那么物体1的名词类别序号就是85
- 比如图片1的
- 最后根据关系的类别序号
predicates
来将关系序号换成关系英文,再根据名词序号ind_to_classes
把名词序号换成对应名词英文
- 先将其替换成格式如下:
predicates
如下
['__background__', 'above', 'across', 'against', 'along', 'and', 'at', 'attached to', 'behind', 'belonging to', 'between', 'carrying', 'covered in', 'covering', 'eating', 'flying in', 'for', 'from', 'growing on', 'hanging from', 'has', 'holding', 'in', 'in front of', 'laying on', 'looking at', 'lying on', 'made of', 'mounted on', 'near', 'of', 'on', 'on back of', 'over', 'painted on', 'parked on', 'part of', 'playing', 'riding', 'says', 'sitting on', 'standing on', 'to', 'under', 'using', 'walking in', 'walking on', 'watching', 'wearing', 'wears', 'with']
ind_to_classes
如下:
['__background__', 'airplane', 'animal', 'arm', 'bag', 'banana', 'basket', 'beach', 'bear', 'bed', 'bench', 'bike', 'bird', 'board', 'boat', 'book', 'boot', 'bottle', 'bowl', 'box', 'boy', 'branch', 'building', 'bus', 'cabinet', 'cap', 'car', 'cat', 'chair', 'child', 'clock', 'coat', 'counter', 'cow', 'cup', 'curtain', 'desk', 'dog', 'door', 'drawer', 'ear', 'elephant', 'engine', 'eye', 'face', 'fence', 'finger', 'flag', 'flower', 'food', 'fork', 'fruit', 'giraffe', 'girl', 'glass', 'glove', 'guy', 'hair', 'hand', 'handle', 'hat', 'head', 'helmet', 'hill', 'horse', 'house', 'jacket', 'jean', 'kid', 'kite', 'lady', 'lamp', 'laptop', 'leaf', 'leg', 'letter', 'light', 'logo', 'man', 'men', 'motorcycle', 'mountain', 'mouth', 'neck', 'nose', 'number', 'orange', 'pant', 'paper', 'paw', 'people', 'person', 'phone', 'pillow', 'pizza', 'plane', 'plant', 'plate', 'player', 'pole', 'post', 'pot', 'racket', 'railing', 'rock', 'roof', 'room', 'screen', 'seat', 'sheep', 'shelf', 'shirt', 'shoe', 'short', 'sidewalk', 'sign', 'sink', 'skateboard', 'ski', 'skier', 'sneaker', 'snow', 'sock', 'stand', 'street', 'surfboard', 'table', 'tail', 'tie', 'tile', 'tire', 'toilet', 'towel', 'tower', 'track', 'train', 'tree', 'truck', 'trunk', 'umbrella', 'vase', 'vegetable', 'vehicle', 'wave', 'wheel', 'window', 'windshield', 'wing', 'wire', 'woman', 'zebra']
使用如下的替换函数,其中./gt_and_pred_info.json
和predicates
和ind_to_classes
上面已经提供了
(对了,下面的代码,我把obj_scores小于0.1的faster rcnn的预测结果过滤掉了,因为确实用不到,本身也是应该过滤掉)
# 输入:关系和类别名对应关系
# predicates 和 ind_to_classes
# gt_classes和gt_boxes一一对应,指代的当前图片中第几个bbox所对应的物体的类别序号(这个序号可以通过ind_to_classes和英文单词进行一一对应)
# 同样,pred_classes也是和pred_boxes是一一对应的,指代的也是当前图片中第几个bbox所对应的物体的类别序号(这个序号可以通过ind_to_predicates和英文单词进行一一对应。)
def triple_translation_json(predicates,ind_to_classes):
# 从本地文件读取JSON数据
file_path = './gt_and_pred_info.json'
with open(file_path, 'r', encoding='utf-8') as file:
datas = json.load(file)
print(datas)
output_data = []
for img_id,data in enumerate(datas):
image_path = data['img_file']
img_name = image_path.split('/')[-1] # 或img_name = os.path.basename(img_info)
gt_unrevised_triplets = data['gt_rels']
gt_boxes = data['gt_boxes']
gt_classes = data['gt_classes']
pred_boxes = data['pred_boxes']
pred_classes = data['pred_classes']
obj_scores = data['obj_scores']
# 第一步:将gt序号三元组替换为真实的英文名字
gt_temp_triplets = []
for triplet in gt_unrevised_triplets:
gt_triplet = [data['gt_classes'][triplet[0]],triplet[2],data['gt_classes'][triplet[1]]] # 先将其替换成对应的识别的物体,再兑换成英文名字
gt_temp_triplets.append(gt_triplet)
# 将真实和预测三元组转换为英文名字
gt_triplets = replace_with_names(gt_temp_triplets)
# 第二步:把gt_classes换成英文单词。
gt_classes_name = []
for gt_class_index in gt_classes:
gt_class_name = ind_to_classes[gt_class_index]
gt_classes_name.append(gt_class_name)
# 第三步,把pred_classes换成英文单词。
pred_classes_name = []
for pred_class_index in pred_classes:
pred_class_name = ind_to_classes[pred_class_index]
pred_classes_name.append(pred_class_name)
# 第四步,对pred_classes做筛选,把相应的打分超过0.1的留下,其余的删去:
# 筛选后的变量
filtered_pred_classes = []
filtered_obj_scores = []
filtered_pred_boxes = []
# 遍历 obj_scores 并根据条件筛选
for i in range(len(obj_scores)):
if obj_scores[i] >= 0.1:
# filtered_pred_classes.append(pred_classes[i]) # 这个是序号
filtered_pred_classes.append(pred_classes_name[i])
filtered_obj_scores.append(obj_scores[i])
filtered_pred_boxes.append(pred_boxes[i])
# 将结果添加到输出列表中
output_data.append({
'image_id': img_id,
'image_path': img_name,
'gt_boxes': gt_boxes,
'gt_classes': gt_classes_name,
'gt_triplets': gt_triplets,
'pred_boxes': filtered_pred_boxes,
# 'pred_classes': pred_classes_name,
'pred_classes': filtered_pred_classes,
# 'obj_scores': obj_scores
'obj_scores': filtered_obj_scores
})
# 将结果保存到新的JSON文件中
with open("gt_and_pred_english.json", 'w', encoding='utf-8') as file:
json.dump(output_data, file, ensure_ascii=False, indent=4)
def replace_with_names(triplets):
replaced_triplets = []
for triplet in triplets:
replaced_triplet = [
ind_to_classes[triplet[0]],
predicates[triplet[1]],
ind_to_classes[triplet[2]]
]
replaced_triplets.append(replaced_triplet)
return replaced_triplets
即生成的最终替换好的gt_and_pred_english.json文件:
可以看到,里面的gt_classes
,gt_triplets
,pred_boxes
,pred_classes
都已经换成对应的英文名词了
把序号替换成英文单词的完美新json文件下载链接:
链接:https://pan.baidu.com/s/15A2NfXFJVnMwoZPBfnLbvQ
提取码:3ppn
–来自百度网盘超级会员V8的分享
再次更新,添加图片大小(宽度和高度)
更新的代码(新增加文件的宽和高):
这回新增加了几行代码,让文件保存了每一张测试图片的宽度和高度:
新增加代码块
# 获取图片的宽和高
with Image.open(img_full_path) as img:
width, height = img.size
import json
import os
import sys
from PIL import Image
# 输入:关系和类别名对应关系
# predicates 和 ind_to_classes
# gt_classes和gt_boxes一一对应,指代的当前图片中第几个bbox所对应的物体的类别序号(这个序号可以通过ind_to_classes和英文单词进行一一对应)
# 同样,pred_classes也是和pred_boxes是一一对应的,指代的也是当前图片中第几个bbox所对应的物体的类别序号(这个序号可以通过ind_to_predicates和英文单词进行一一对应。)
def triple_translation_json(predicates,ind_to_classes):
# 从本地文件读取JSON数据
file_path = './gt_and_pred_info.json'
with open(file_path, 'r', encoding='utf-8') as file:
datas = json.load(file)
print(datas)
output_data = []
for img_id,data in enumerate(datas):
image_path = data['img_file']
img_name = image_path.split('/')[-1] # 或img_name = os.path.basename(img_info)
img_full_path = os.path.join('C:\\我的文件\\数据集\\VG_100K', img_name)
# 获取图片的宽和高
with Image.open(img_full_path) as img:
width, height = img.size
gt_unrevised_triplets = data['gt_rels']
gt_boxes = data['gt_boxes']
gt_classes = data['gt_classes']
pred_boxes = data['pred_boxes']
pred_classes = data['pred_classes']
obj_scores = data['obj_scores']
# 第一步:将gt序号三元组替换为真实的英文名字
gt_temp_triplets = []
for triplet in gt_unrevised_triplets:
gt_triplet = [data['gt_classes'][triplet[0]],triplet[2],data['gt_classes'][triplet[1]]] # 先将其替换成对应的识别的物体,再兑换成英文名字
gt_temp_triplets.append(gt_triplet)
# 将真实和预测三元组转换为英文名字
gt_triplets = replace_with_names(gt_temp_triplets)
# 第二步:把gt_classes换成英文单词。
gt_classes_name = []
for gt_class_index in gt_classes:
gt_class_name = ind_to_classes[gt_class_index]
gt_classes_name.append(gt_class_name)
# 第三步,把pred_classes换成英文单词。
pred_classes_name = []
for pred_class_index in pred_classes:
pred_class_name = ind_to_classes[pred_class_index]
pred_classes_name.append(pred_class_name)
# 第四步,对pred_classes做筛选,把相应的打分超过0.1的留下,其余的删去:
# 筛选后的变量
filtered_pred_classes = []
filtered_obj_scores = []
filtered_pred_boxes = []
# 遍历 obj_scores 并根据条件筛选
for i in range(len(obj_scores)):
if obj_scores[i] >= 0.1:
# filtered_pred_classes.append(pred_classes[i]) # 这个是序号
filtered_pred_classes.append(pred_classes_name[i])
filtered_obj_scores.append(obj_scores[i])
filtered_pred_boxes.append(pred_boxes[i])
# 将结果添加到输出列表中
output_data.append({
'image_id': img_id,
'image_path': img_name,
'width': width,
'height': height,
'gt_boxes': gt_boxes,
'gt_classes': gt_classes_name,
'gt_triplets': gt_triplets,
'pred_boxes': filtered_pred_boxes,
# 'pred_classes': pred_classes_name,
'pred_classes': filtered_pred_classes,
# 'obj_scores': obj_scores
'obj_scores': filtered_obj_scores
})
# 将结果保存到新的JSON文件中
with open("gt_and_pred_english.json", 'w', encoding='utf-8') as file:
json.dump(output_data, file, ensure_ascii=False, indent=4)
def replace_with_names(triplets):
replaced_triplets = []
for triplet in triplets:
replaced_triplet = [
ind_to_classes[triplet[0]],
predicates[triplet[1]],
ind_to_classes[triplet[2]]
]
replaced_triplets.append(replaced_triplet)
return replaced_triplets
if __name__ == "__main__":
with (open('./data_val.json', 'r', encoding='utf-8') as file):
data1 = json.load(file)
predicates = []
ind_to_classes = []
for img_id,image_name_long in enumerate(data1['filenames']):
img_name = image_name_long.split('/')[-1] # 或者 img_name = os.path.basename(img_info)
# img_id 和img_name 就是我们需要用到的内容。
# 读取关系和物体名称对应关系
predicates = data1['ind_to_predicates']
ind_to_classes = data1['ind_to_classes']
break
triple_translation_json(predicates, ind_to_classes)
新生成的文件下载地址:
通过百度网盘分享的文件:gt_and_pred_english - 1.json
链接:https://pan.baidu.com/s/1l8UKJpYzFu_9zjiGnfYuJA
提取码:2ri6
–来自百度网盘超级会员V8的分享

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)