[LAB 16 · 点、框与负提示:分割规则基线](/course/notebooks/d83defa954034769a1ee94e3ea48640a.html) # 一个点为什么不总能确定一个对象 · 实现代码 [独立阅读](/course/notebook-blocks/a938e2aaafcf413d96db608c3cb1cfbc.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') ```