@@ -23,5 +23,192 @@ author:
23
23
> 论文: [ https://openaccess.thecvf.com/content/CVPR2024/papers/Li_LASO_Language-guided_Affordance_Segmentation_on_3D_Object_CVPR_2024_paper.pdf ] ( https://openaccess.thecvf.com/content/CVPR2024/papers/Li_LASO_Language-guided_Affordance_Segmentation_on_3D_Object_CVPR_2024_paper.pdf )
24
24
> 代码: [ https://github.com/yl3800/LASO ] ( https://github.com/yl3800/LASO )
25
25
26
+
27
+ 这篇论文提出了一项新的任务和一个配套的数据集,旨在推动 ** 语言引导下的** 3D对象功能区域分割(Language-guided Affordance Segmentation on 3D Object, 简称 LASO)。
28
+
26
29
## 数据集
27
30
31
+ ### 1. 基础数据来源
32
+
33
+ 数据集基于 ** 3D-AffordanceNet** 提供的点云和功能区域标注构建:
34
+
35
+ - 每个物体都以点云形式表示;
36
+ - 点云中的每个点被标注为支持一个或多个功能类型(multi-class affordance labels),例如 grasp、open、lift、move 等;
37
+ - 这些功能标注是人工标注的,具有语义意义;
38
+
39
+ > ** 为什么使用 3D-AffordanceNet?**
40
+ > - 因为它提供了高质量的点云和功能标注,能够很好地支持 LASO 的目标:根据自然语言问题找出与之相关的功能区域。
41
+
42
+
43
+ ### 2. 构建问题(Question Crafting)
44
+
45
+ 1 . ** 选取物体-功能组合** :
46
+ - 从 3D-AffordanceNet 中选取了 ** 58 种物体-功能组合** (如 mug-grasp、door-open 等);
47
+ 2 . ** 手工设计问题** :
48
+ - 对每种组合手工编写 ** 5 个代表性问题** ;
49
+ 3 . ** 使用 GPT-4 扩展生成更多问题** :
50
+ - 使用 GPT-4 为每个组合额外生成 ** 10 个问题** ;
51
+ - 总共得到 ** 870 个专家设计的问题** (58 × 15 = 870);
52
+
53
+
54
+ ![ Affordance-Question数据可视化] ( LASO/1.png )
55
+
56
+
57
+
58
+ 在扩展过程中,GPT-4 生成的问题遵循以下三个关键原则,以确保问题多样性和语义丰富性:
59
+
60
+ | 原则 | 描述 |
61
+ | ------| ------|
62
+ | ** Contextual Enrichment(上下文丰富化)** | 添加更多上下文细节,使问题更具体地连接目标对象的功能;<br >例:将 “Grasping scissors: top choice?” 改为 “Identify the key points on the scissors that ensure successful grasping.” |
63
+ | ** Concise Phrasing(简洁表达)** | 提炼问题本质,使其简短但仍有意义; |
64
+ | ** Structural Diversity(结构多样性)** | 使用不同句式结构(疑问句、陈述句等),防止模型偏向特定句式或长度; |
65
+
66
+ ### 3. 标注 GT Mask(Ground Truth Mask)
67
+
68
+ 对于每个问题,结合其对应的功能类型和原始点云标注信息,构造出对应的二值掩码 ` gt_mask ` :
69
+
70
+ - 每个点是否属于当前问题描述的功能区域;
71
+ - ` gt_mask ` 是 ` (N,) ` 形状的一维数组,其中 N 是点数;
72
+ - 数值可以是 0/1(binary mask),也可以是** 软标签(soft label)** ,表示点属于该功能区域的概率;
73
+ - 软标签通常用于边界模糊区域,反映点与功能核心区域的距离远近;
74
+
75
+ > 💡 注意:这些功能标签仅用于构造问题和定位正确功能区域,在训练和测试中不作为显式监督信号。
76
+
77
+ ### 4. 数据集组织方式
78
+
79
+ 数据总量:
80
+
81
+ - ** 总样本数** :19,751 个点云-问题配对;
82
+ - ** 物体类别数** :23 类;
83
+ - ** 功能类型数** :17 类;
84
+ - ** 问题总数** :870 个专家设计的问题;
85
+ - ** 每个物体类别可有多个形状实例** ;
86
+ - ** 一个问题可以作用于多个物体类别** (泛化能力);
87
+
88
+ 数据集设置(两种模式):
89
+
90
+ 🔹 Seen(见过)
91
+
92
+ - 训练和测试阶段共享相似的物体类别和功能类型的分布;
93
+ - 目的是评估模型在熟悉场景下的表现;
94
+
95
+ 🔹 Unseen(未见)
96
+
97
+ - 某些功能类型在特定物体类别下会从训练集中省略,但在测试集中保留;
98
+ - ** 目的是测试模型对新组合的泛化能力;**
99
+ - 例如:模型在训练期间学会了抓取包和杯子,但测试时要求“抓取耳机”——这是训练中未曾遇到过的功能-物体组合;
100
+
101
+ 数据划分方式:
102
+
103
+ | 分区 | 物体类别数 | 问题数 | 样本数 |
104
+ | ------| -------------| --------| ---------|
105
+ | Train | 6883 | 638 | 16,120 |
106
+ | Val | 516 | 58 | 1,215 |
107
+ | Test | 1035 | 174 | 2,416 |
108
+
109
+ ### 5. 数据增强与配对策略
110
+
111
+ 训练阶段:
112
+
113
+ - 每次迭代中,每个形状实例随机匹配一个与其功能类型一致的问题;
114
+ - 随机配对使模型暴露于各种语义上下文中,提升泛化能力;
115
+
116
+ 推理阶段(验证 & 测试):
117
+
118
+ - 问题配对是固定的;
119
+ - 所有问题专属于评估阶段,不在训练中透露;
120
+ - 确保推理一致性,保持评估完整性;
121
+
122
+
123
+ ### 6. 数据集统计信息(来自论文图3)
124
+
125
+ | 维度 | 内容 |
126
+ | ------| ------|
127
+ | 功能类型 | 17 类,如 grasp、open、lift、move 等 |
128
+ | 物体类别 | 23 类,如 mug、microwave、chair、door 等 |
129
+ | 物体-功能组合 | 58 种唯一组合(object-affordance pairs) |
130
+ | 问题总数 | 870 个定制化问题 |
131
+ | 点云-问题配对 | 19,751 对 |
132
+ | 点云来源 | 来自 3D-AffordanceNet,每个点云约 2048 个点 |
133
+
134
+ ### 7. 代码实现
135
+
136
+ 数据集加载的核心代码实现如下:
137
+
138
+ ``` python
139
+ class AffordQ (Dataset ):
140
+
141
+ def __init__ (self ,
142
+ split = ' train' ,
143
+ ** kwargs
144
+ ):
145
+ # 数据集存放目录
146
+ data_root= ' LASO_dataset'
147
+ # 数据集类型: 训练集,评估集,测试集
148
+ self .split = split
149
+ # 所支持的23种物体类型和17种功能类型
150
+ classes = [" Bag" , " Bed" , " Bowl" ," Clock" , " Dishwasher" , " Display" , " Door" , " Earphone" , " Faucet" ,
151
+ " Hat" , " StorageFurniture" , " Keyboard" , " Knife" , " Laptop" , " Microwave" , " Mug" ,
152
+ " Refrigerator" , " Chair" , " Scissors" , " Table" , " TrashCan" , " Vase" , " Bottle" ]
153
+
154
+ afford_cl = [' lay' ,' sit' ,' support' ,' grasp' ,' lift' ,' contain' ,' open' ,' wrap_grasp' ,' pour' ,
155
+ ' move' ,' display' ,' push' ,' pull' ,' listen' ,' wear' ,' press' ,' cut' ,' stab' ]
156
+
157
+ self .cls2idx = {cls .lower():np.array(i).astype(np.int64) for i, cls in enumerate (classes)}
158
+ self .aff2idx = {cls :np.array(i).astype(np.int64) for i, cls in enumerate (afford_cl)}
159
+
160
+ with open (os.path.join(data_root, f ' anno_ { split} .pkl ' ), ' rb' ) as f:
161
+ self .anno = pickle.load(f)
162
+
163
+ with open (os.path.join(data_root, f ' objects_ { split} .pkl ' ), ' rb' ) as f:
164
+ self .objects = pickle.load(f)
165
+
166
+ # Load the CSV file, and use lower case
167
+ self .question_df = pd.read_csv(os.path.join(data_root, ' Affordance-Question.csv' ))
168
+
169
+ self .len = len (self .anno)
170
+
171
+ print (f " load { split} set successfully, lenth { len (self .anno)} " )
172
+
173
+ # sort anno by object class and affordance type
174
+ self .sort_anno = {}
175
+ for item in sorted (self .anno, key = lambda x : x[' class' ]):
176
+ key = item[' class' ]
177
+ value = {' shape_id' : item[' shape_id' ], ' mask' : item[' mask' ], ' affordance' : item[' affordance' ]}
178
+
179
+ if key not in self .sort_anno:
180
+ self .sort_anno[key] = [value]
181
+ else :
182
+ self .sort_anno[key].append(value)
183
+
184
+
185
+ def find_rephrase (self , df , object_name , affordance ):
186
+ qid = str (np.random.randint(1 , 15 )) if self .split == ' train' else ' 0'
187
+ qid = ' Question' + qid
188
+ result = df.loc[(df[' Object' ] == object_name) & (df[' Affordance' ] == affordance), [qid]]
189
+ if not result.empty:
190
+ # return result.index[0], result.iloc[0]['Rephrase']
191
+ return result.iloc[0 ][qid]
192
+ else :
193
+ raise NotImplementedError
194
+
195
+
196
+ def __getitem__ (self , index ):
197
+ data = self .anno[index]
198
+ shape_id = data[' shape_id' ]
199
+ cls = data[' class' ]
200
+ affordance = data[' affordance' ]
201
+ gt_mask = data[' mask' ]
202
+ point_set = self .objects[str (shape_id)]
203
+ point_set,_,_ = pc_normalize(point_set)
204
+ point_set = point_set.transpose()
205
+
206
+ question = self .find_rephrase(self .question_df, cls , affordance)
207
+ affordance = self .aff2idx[affordance]
208
+
209
+ return point_set, self .cls2idx[cls ], gt_mask, question, affordance
210
+ ```
211
+
212
+ ### 8. 总结
213
+
214
+ LASO 数据集基于 3D-AffordanceNet 的点云和功能标注,结合人工+GPT-4 生成的多样化问题,构造出 19,751 个点云-问题配对,旨在实现语言引导下的 3D 功能区域分割,推动 3D 视觉与大语言模型(LLM)的深度融合。
0 commit comments