# LAB 03 · 空间信息:表示、采样与掩码 按问题继续 同源场景标签、插值、信息碰撞的轻量解析代码 对应课堂(12 页) 可先阅读已有结果,再决定是否运行。重算时请核对各节记录的数据、参数、环境与日期。 **轻量空间实验:看图与读数即可完成一条问题线。** 对应 [P25](/course/pages/l3-r2-p25.html) 和 [P41](/course/pages/l3-r2-p41.html)—[P45](/course/pages/l3-r2-p45.html)。这里保留同一照片与手工标注,检验坐标读取和表示碰撞,不训练检测器或分割器。 [四种输出的解释](/course/blocks/spatial-four-answers.html) · [二维四邻点算例](/course/blocks/bilinear-four-neighbors.html) · [相同表示的推导](/course/blocks/representation-collision-proof.html) · [真实模型为何仍能从对齐受益](/course/blocks/roi-align-paper-evidence.html)。 同一场景,先改变要交付的信息,再检查区域坐标怎样被读取。可以只读四幅图和保存结果,也可以修改下面的小型代码;不训练检测器。 [第三讲导读](/course/guide.html) · [CLS 02](https://deepnote.com/workspace/ise3309jingao-5ba66b0a-4283-4f5a-ae06-3f68d3201e99/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/f9ab632ba16b4f2084669791cba6ba85?utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_content=f9ab632ba16b4f2084669791cba6ba85&utm_term=get_notebook) ## 先观察:两个杯子、一本书与遮挡 !['同一桌面原图'](/course/knowledge-assets/46ffa1170be676ea38dfc1ee.jpg) **先预测:** “有杯子”能说明杯子有几只、在哪里、把手内的空洞属于谁吗?蓝杯被书遮住一部分;本活动只标可见轮廓。下列图是同一照片的手工教学标注。 [此段独立阅读](/course/notebook-blocks/2f439ca34a724eb18d159d883738618c.html) ### 1. 类别与框 ![1. 类别与框](/course/knowledge-assets/9519a7fe8442b498fb4600c9.jpg) 红杯框 [177,238,390,351]、蓝杯框 [641,235,386,249]、书框 [596,411,860,362]。这里按 x、y、宽、高记录,原图坐标为1536×1024。框内仍包含背景。 ImageGen 场景+代码绘制教学标注,非模型预测。 [此段独立阅读](/course/notebook-blocks/ed1a18aa9f8b43929619f2e72ff15160.html) ### 2. 语义像素 ![2. 语义像素](/course/knowledge-assets/b0ea98b0279905229860f0cf.jpg) 两个杯子使用同一个杯子类别;把手空洞与杯身不属于同一像素集合。 ImageGen 场景+代码绘制教学标注,非模型预测。 [此段独立阅读](/course/notebook-blocks/664c0174befe4f9598e78391fe5643fb.html) ### 3. 实例掩码 ![3. 实例掩码](/course/knowledge-assets/bd15e99e56cc9220deed3d6c.jpg) 两个杯子同类,但分别保留 cup-red、cup-blue 的实例身份;书为独立对象。改变类别或实例身份不会自动改变可见轮廓。 ImageGen 场景+代码绘制教学标注,非模型预测。 [此段独立阅读](/course/notebook-blocks/1761803a29b74f3abfb120f36f3d725c.html)展开完整实现代码 ``` # 本册独立素材准备:内嵌预览与精确原图坐标,不下载外站,也不依赖其他 notebook 的变量。 from pathlib import Path import base64, json from IPython.display import SVG, display scene_uri = 'https://codingai-lec03.pages.dev/course/knowledge-assets/46ffa1170be676ea38dfc1ee.jpg' annotation = {'version': 'L03-r2-20260922', 'image': 'tabletop-occlusion.png', 'size': [1536, 1024], 'label': '手工教学标注:可见轮廓,非模型输出或数据集真值', 'objects': [{'id': 'cup-red', 'category': 'cup', 'polygon': [[280, 270], [295, 251], [362, 241], [448, 242], [527, 253], [565, 270], [562, 361], [554, 454], [542, 532], [526, 565], [491, 579], [432, 586], [369, 582], [329, 568], [307, 541], [297, 516], [258, 497], [224, 471], [194, 433], [179, 392], [178, 356], [190, 326], [210, 308], [242, 303], [278, 314]], 'holes': [[[280, 351], [251, 328], [227, 328], [209, 343], [200, 368], [204, 400], [219, 432], [244, 459], [276, 480], [290, 481]]], 'box': [177, 238, 390, 351]}, {'id': 'cup-blue', 'category': 'cup', 'polygon': [[642, 266], [663, 248], [732, 238], [814, 238], [888, 249], [925, 267], [925, 306], [954, 296], [985, 296], [1009, 310], [1022, 334], [1025, 366], [1018, 396], [1010, 418], [934, 435], [850, 450], [746, 466], [659, 482], [650, 414], [644, 341]], 'holes': [[[925, 348], [944, 323], [965, 318], [986, 326], [1000, 347], [1002, 373], [993, 404], [984, 424], [919, 438]]], 'box': [641, 235, 386, 249]}, {'id': 'book', 'category': 'book', 'polygon': [[602, 500], [626, 490], [1051, 412], [1450, 548], [1451, 560], [1438, 576], [1438, 633], [1454, 648], [918, 770], [602, 586], [597, 560], [598, 516]], 'holes': [], 'box': [596, 411, 860, 362]}]} asset_dir = Path.cwd() / 'lecture03-assets-r2' asset_dir.mkdir(exist_ok=True) preview_file = asset_dir / 'tabletop-occlusion-preview.jpg' if not preview_file.exists(): preview_file.write_bytes(base64.b64decode(scene_uri.split(',',1)[1])) (asset_dir / 'scene-annotations.json').write_text(json.dumps(annotation,ensure_ascii=False,indent=2)) print('可用材料:', preview_file.name, 'scene-annotations.json') print('标注坐标系:', annotation['size'], ';图片预览768×512,展示时同比例映射。') # 修改这一项为 cup-red、cup-blue 或 book,预测红框和局部窗口怎样改变。 selected_id = 'cup-blue' obj = next(o for o in annotation['objects'] if o['id']==selected_id) x,y,w,h = obj['box'] print('所选对象:',selected_id,'类别:',obj['category'],'框(x,y,w,h):',[x,y,w,h]) svg = f'' display(SVG(svg)) # 将所选框显示在归一化的局部窗口;不把此教学裁剪称为 RoIAlign。 local_svg = f'' display(SVG(local_svg)) ``` [此段独立阅读](/course/notebook-blocks/231837089e9a4369aa7529f300a99919.html)展开完整实现代码 ``` # 本格独立:先预测,再修改 x_image / 特征值,不用前格变量。 import math feature = [0.,1.,2.,6.,7.] def linear_at(x_image, stride, values): u=x_image/stride if not 0<=u<=len(values)-1: raise ValueError('采样位置超出已有特征;请一起检查坐标与特征范围') lo=math.floor(u); hi=min(lo+1,len(values)-1) a=u-lo return u,(1-a)*values[lo]+a*values[hi] assert linear_at(35,16,feature)==(2.1875,2.75) x_image, stride = 35.,16. u,value=linear_at(x_image,stride,feature) print('原图x / stride =',u,';线性插值 =',value) A=[[1.,0.],[1.,0.]];B=[[0.,1.],[0.,1.]] def encode(m): return sum(map(sum,m))/4, sum(r[0]-r[1] for r in m)/2 fa,fb=encode(A),encode(B) print('只留均值:',fa[0],fb[0]) print('增加左列−右列通道:',fa,fb) print('均值各放大为2×2:',[[fa[0]]*2]*2,[[fb[0]]*2]*2) assert fa==(0.5,1.0) and fb==(0.5,-1.0) ``` [此段独立阅读](/course/notebook-blocks/c29bd696d6a14697aec8bacd7fc5b1a8.html) ## 读取结果,解释改动 默认蓝杯框为 `[641,235,386,249]`;选择红杯后框换为 `[177,238,390,351]`。图像与标注引用同一源场景,局部窗口按该框显示。运行准备只写本课素材目录,不加载模型。 数值默认输出:`原图x / stride = 2.1875;线性插值 = 2.75`。这是约定 `u=x/stride` 的一维教学例;真实二维 RoIAlign 还包括区域分格、双线性采样及汇总。 均值编码均为 `0.5`;其余特征和框相同、后续不能回看原图时,放大或改采样仍没有新差别。新增“左列−右列”后,表示为 `(0.5,+1)` 与 `(0.5,−1)`。 **现在作判断:** 若连续位置读错了,应改采样;若表示把两种输入变成同一个值,应检查编码器留下的信息。真实 Mask R-CNN 的对齐训练对照,与这里固定同一表示的构造是两种实验。 **自己改一个条件:** 选蓝杯或红杯;把原图 x 改成 36;把右邻特征 6 改成 10;为甲乙保留或删去差分通道。每次先写预测,再读图/数值并解释。无需提交编码作业。 **阅读位置:** 本册是[像素、边界与对象身份](/course/study/pixels-instances.html)路径中的采样短练习。先解释一个坐标或一次信息碰撞;需要学习模型时再到 LAB11,不必把全部短练习顺序做完。 **接下来按问题选择:** 要把采样从一维扩到二维,读 [四个邻点如何读出 2.5](/course/blocks/bilinear-four-neighbors.html);要检验模型真能从 RGB 得到轮廓,读 [LAB 11](https://deepnote.com/workspace/ise3309jingao-5ba66b0a-4283-4f5a-ae06-3f68d3201e99/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/9e268706471944e3a59e6f568f9ce9a3?utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_content=9e268706471944e3a59e6f568f9ce9a3&utm_term=get_notebook)。本册的 SVG 裁剪不是调用 RoIAlign,平均值碰撞也不是分割模型训练结果,两项准确身份使它们能和完整实验互相补充。 [此段独立阅读](/course/notebook-blocks/67d424947f214e6e8281cd50e173751d.html)