# LAB 16 · 点、框与负提示:分割规则基线 按问题继续 像素连通域、正负点/框提示、局部/整体多义性 对应课堂(6 页) 可先阅读已有结果,再决定是否运行。重算时请核对各节记录的数据、参数、环境与日期。 **学习路径:** [像素、边界与对象身份](/course/study/pixels-instances.html) · [一句话指向哪个对象](/course/study/grounding-interface.html)。两个入口引用同一份现有材料,不需要重复阅读或运行。 这是 [P46–47 提示式分割](/course/pages/l3-r2-p46.html) 的按需短练习,不是 SAM 权重实验。输入同一张 RGB 图、一个正点及可选负点/框,颜色距离与连通域规则返回 mask;没有参数训练。 先看 [四种已保存输出](/course/blocks/sam-rule-baseline-explained.html),再只改一种条件:颜色容差、负点或框。记录返回面积或边界怎样改变,说明变化来自增加的提示信息还是规则本身的假设。 如果疑问是“训练后模型如何学会响应提示”,转到 [SAM 的任务训练](/course/blocks/sam-task-training.html);如果已经理解接口,可回 [CLS 02](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/f9ab632ba16b4f2084669791cba6ba85) 接视觉语言主线,无需额外运行本册。 ## 一个点为什么不总能确定一个对象 输入是自行绘制的 48×64 RGB 图像:相邻的红色外壳和深红色内部零件,另有蓝色物体。正点、负点和矩形是使用者给出的条件,而非正确 mask。本例使用颜色距离与连通域的确定性算法,完整读入像素并返回 mask;它不训练,也不是 SAM。我们保留原来的“同一点同时落在局部和整体”例子,但现在实际改变提示和阈值,检查返回区域。 先预测:扩大颜色容差,正点的连通区域会增加还是减少?增加落在外壳上的负点会如何影响结果?负点在此算法中添加的是颜色排除规则,与 SAM 学到的提示编码不同。 [本册算法与四项已保存输出](/course/blocks/sam-rule-baseline-explained.html) · [SAM 的能力实际怎样训练出来](/course/blocks/sam-task-training.html) [此段独立阅读](/course/notebook-blocks/b800ace904634fa1923a4a15bf3725cc.html)展开完整实现代码 ``` # Writable ephemeral workspace for detached readonly cloud runs. import os, tempfile os.chdir(tempfile.mkdtemp(prefix='lec03_lab16_')) import numpy as np from pathlib import Path import matplotlib; matplotlib.use('Agg') import matplotlib.pyplot as plt out=Path('lab16-results'); out.mkdir(exist_ok=True) image=np.full((48,64,3),.94); image[8:39,7:34]=[.8,.18,.15] image[18:29,17:27]=[.48,.10,.08]; image[13:37,43:57]=[.12,.25,.8] def segment(image,positive,tolerance,negative=None,box=None): x,y=positive; seed=image[y,x]; allowed=np.linalg.norm(image-seed,axis=-1).15 if box is not None: x0,y0,x1,y1=box; crop=np.zeros(allowed.shape,bool); crop[y0:y1,x0:x1]=True; allowed &= crop result=np.zeros(allowed.shape,bool); stack=[(x,y)] while stack: x,y=stack.pop() if not (0<=x<64 and 0<=y<48) or result[y,x] or not allowed[y,x]: continue result[y,x]=True; stack.extend([(x-1,y),(x+1,y),(x,y-1),(x,y+1)]) return result configs=[('tight',.2,None,None),('loose',.5,None,None),('negative',.5,(10,10),None),('box',.5,None,(16,17,28,30))] masks=[segment(image,(21,23),t,n,b) for _,t,n,b in configs] fig,axs=plt.subplots(1,5,figsize=(12,3)); axs[0].imshow(image); axs[0].plot(21,23,'g+'); axs[0].set_title('RGB + positive point') for ax,(name,*_),mask in zip(axs[1:],configs,masks): ax.imshow(mask,vmin=0,vmax=1); ax.set_title(name+' area='+str(mask.sum())) for ax in axs: ax.axis('off') fig.tight_layout(); fig.savefig(out/'lab16-prompts.png',dpi=150); plt.close(fig) assert masks[0].sum()==110 and masks[1].sum()==837 print({name:int(m.sum()) for (name,*_),m in zip(configs,masks)}) print('negative removes similar outer-shell pixels; box clips, neither proves learned object semantics') ``` [此段独立阅读](/course/notebook-blocks/a938e2aaafcf413d96db608c3cb1cfbc.html) ## 已完成的基准运行 以下是本轮本地独立 Python 进程的实际标准输出,云端执行另行记录。 ``` {'tight': 110, 'loose': 837, 'negative': 110, 'box': 156} negative removes similar outer-shell pixels; box clips, neither proves learned object semantics ``` 紧容差只保留内部 110 像素;宽容差合并到 837 像素外壳。负点回到 110,框则保留框内相连部分。这说明提示与算法假设共同决定输出,框还可能截断对象。 ![同一RGB输入的四种提示结果](/assets/display/4a9a30188e394075dc0e66fa.webp) SAM 把图像与提示分别编码,由 mask decoder 预测多个候选和质量分数;不是这段颜色规则。真实模型使用流程见 [官方 SAM predictor](https://github.com/facebookresearch/segment-anything/blob/main/notebooks/predictor_example.ipynb)。本次没有执行 SAM checkpoint。比较算法时固定这张图与提示,保存返回 mask,不把任意一个包含正点的 mask 都叫正确答案。下一步只把正点移到蓝色物体,解释颜色阈值是否还足够;与 [LAB 11 像素预测](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/9e268706471944e3a59e6f568f9ce9a3) 对照:模型类别预测和使用者选择对象是两个问题。 [此段独立阅读](/course/notebook-blocks/be0ffb282ff049c88a51c23102954748.html) #### 不运行也能检查:一个点包含在两个区域中 在 8×8 网格里,让局部区域为行列 2–3 的四个格子,整体区域为行列 1–6 的 36 个格子。点 (2,2) 同时属于两者,所以“包含正点”无法唯一规定目标。当前上方 RGB 实验进一步用容差、负点和框实际选择区域。 [从这一歧义读回提示式分割接口](/course/blocks/sam-prompt-contract.html)。 [此段独立阅读](/course/notebook-blocks/9c0f03efa4584e448eebaf416a492370.html)