graph_file
graph_file是一个HDF5文件,存储的是与目标检测和关系识别任务相关的信息,这些信息通常以结构化的形式组织。其中的数据可以用来构建图结构,特别是用于场景图。
graph_file可能包含的内容:
(1)目标检测框
- boxes:一个数组,存储每个目标的边界框坐标,如[x1,y1,x2,y2]或 [xc, yc, w, h]
- img_to_first_box 和 img_to_last_box:数组,分别表示每个图像的第一个和最后一个目标检测框的索引。
(2)目标类别标签
- labels:一个数组,存储每个目标的类别
(3)关系信息
relationships:一个数组,存储关系的索引。每条关系通常由两个目标的索引和一个谓词索引组成。如 [obj1_idx, obj2_idx, predicate_idx]
predicates:一个数组,存储关系的谓词(关系类型)。这些谓词通常是一个预定义的谓词映射表中获取的索引值。
(4)数据集的划分
如何构建场景图
从graph_file中读取数据后,可以构建场景图:
1) 提取目标检测框和类别标签:使用 boxes和labels获取每个目标的边界框和类别标签
2) 提取关系信息:使用relationships和predicates获取每条关系的两个目标索引和谓词。
3) 构建图结构:
每个目标检测框作为一个节点。
每条关系作为一条边,连接两个目标节点,并附带谓词信息。
场景图构建案例:
假如有以下数据:
· 目标检测框
boxes = [[10, 10, 50, 50], [20, 20, 60, 60], [30, 30, 70, 70]]
labels = [1, 2, 3] # 假设 1 表示 "cat",2 表示 "dog",3 表示 "table"
· 关系信息
relationships = [[0, 1], [1, 2]]
predicates = [1, 2] # 假设 1 表示 "on",2 表示 "next_to"
可以构建如下场景图:
· 节点:
节点 0:类别 "cat",边界框 [10, 10, 50, 50]
节点 1:类别 "dog",边界框 [20, 20, 60, 60]
节点 2:类别 "table",边界框 [30, 30, 70, 70]
· 边:
边 0:从节点 0 到节点 1,谓词 "on"
边 1:从节点 1 到节点 2,谓词 "next_to"
代码:
- 数据准备
准备目标检测框、类别标签、关系信息:
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
# 目标检测框 (x1, y1, x2, y2)
boxes = np.array([
[10, 10, 50, 50], # 目标 0
[20, 20, 60, 60], # 目标 1
[30, 30, 70, 70] # 目标 2
])
# 类别标签 (假设 1 表示 "cat",2 表示 "dog",3 表示 "table")
labels = np.array([1, 2, 3])
# 关系信息 (目标索引对)
relationships = np.array([
[0, 1], # 目标 0 和目标 1 之间的关系
[1, 2] # 目标 1 和目标 2 之间的关系
])
# 关系谓词 (假设 1 表示 "on",2 表示 "next_to")
predicates = np.array([1, 2])
- 构建场景图
使用Network库构建场景图。
# 创建一个有向图
scene_graph = nx.DiGraph()
# 添加节点 (目标)
for i, (box, label) in enumerate(zip(boxes, labels)):
# 假设我们有一个函数将标签索引转换为类别名称
label_name = {1: "cat", 2: "dog", 3: "table"}[label]
scene_graph.add_node(i, label=label_name, box=box)
# 添加边 (关系)
for (obj1_idx, obj2_idx), predicate in zip(relationships, predicates):
# 假设我们有一个函数将谓词索引转换为关系名称
predicate_name = {1: "on", 2: "next_to"}[predicate]
scene_graph.add_edge(obj1_idx, obj2_idx, predicate=predicate_name)
- 可视化场景图
使用matplotlib和networkx提供的绘图功能可视化场景图
# 绘制场景图
plt.figure(figsize=(8, 6))
pos = nx.spring_layout(scene_graph) # 使用弹簧布局
# 绘制节点
node_labels = {node: data['label'] for node, data in scene_graph.nodes(data=True)}
nx.draw_networkx_nodes(scene_graph, pos, node_size=700, node_color='lightblue')
nx.draw_networkx_labels(scene_graph, pos, labels=node_labels, font_size=12)
# 绘制边
edge_labels = {(u, v): data['predicate'] for u, v, data in scene_graph.edges(data=True)}
nx.draw_networkx_edges(scene_graph, pos, arrowstyle='->', arrowsize=20)
nx.draw_networkx_edge_labels(scene_graph, pos, edge_labels=edge_labels, font_color='red')
# 显示图形
plt.title("Scene Graph Visualization")
plt.axis('off') # 关闭坐标轴
plt.show()
输出结果:
运行上述代码后,将看到一个场景图的可视化结果,其中:
每个节点表示一个目标(例如,“cat”、“dog”、“table”)。
每条边表示两个目标之间的关系(例如,“on”、“next_to”)。