这类问题我又碰上了一次。用 SAM2 官方仓库的 sam2_hiera_large 权重做商品抠图,点选加框选,输出掩码在物体边缘有 1 像素宽的锯齿和空洞,直接拿去合成白底图能看到明显毛边。换成 sam2_hiera_base 也一样,把 points_per_side 从 32 提到 64 只是变慢,边缘仍有缺口。
第一反应是「掩码用 float32 存,转 uint8 时是截断不是四舍五入」,验证下来不成立。
原因不止一个,得分开看。模型输出的 mask logits 直接阈值化,边缘没有做插值;输入图先缩到 1024 再上采样回原图,坐标有半像素偏移;抠图后没做形态学处理,细长结构直接断开。
第一件事是把 logits 上采样到原图尺寸再二值化
python -c "import torch;print(torch.nn.functional.interpolate(torch.randn(1,1,256,256),size=(1080,1920),mode='bilinear').shape)"
接着对掩码做一次闭运算补细缝
python -c "import cv2,numpy as np;m=cv2.imread('mask.png',0);k=np.ones((3,3),np.uint8);cv2.imwrite('mask_fix.png',cv2.morphologyEx(m,cv2.MORPH_CLOSE,k))"
然后比较阈值化与 argmax 两种写法的差异
python -c "import numpy as np;a=np.random.randn(4,4);print((a>0).sum(), a.argmax(0).sum())"
等前面都确认过,再统计修复后前景像素占比是否合理
python -c "import cv2;m=cv2.imread('mask_fix.png',0);print(m.sum()/255)"
恢复的判定其实很直接。合成白底图后边缘不再有毛边,人工抽检 20 张商品图,宽度 3 像素的细绳结构完整保留。
容易忽略的是,掩码后处理不是可选项,阈值化前先上采样、阈值后用 3×3 闭运算,这两步加起来不到 10 毫秒,效果比换更大的权重明显。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
