主图纯白检测,阈值放宽到250会放过252的底

主图上传前加一道纯白检测,阈值最容易写错的地方是放宽到 250。我拿 66 个白底 JPG 和 15 张人造的近白底图把几种常见判法各跑了一遍。整图里 =255 和 ≥250 的占比只差 0.7 到 1.1 个百分点。看着无所谓,可 ≥250 分不出 252 的底和 JPG 自带的杂点。最后留下的判法是找出从图边连进来的那块近白区域,数里面恰好等于 255 的像素占多少。我的线设在 90%。这个 90% 是推断出来的。下面讲它怎么来。

先交代样本。三张实拍图来自维基共享资源:毛绒泰迪熊(Dan Bollinger)、玻璃高脚杯(Kritzolina)、白色运动鞋(JustinLiang522)。许可都是 CC BY-SA 4.0 且不是我拍的,下载的是长边 1707 到 1920 像素的缩放版。抠图和铺白底我用的是图映 ImgIng(imging.cn/),在电脑浏览器里跑快... JPG,要 JPG 就得把 PNG 再拖进压缩转换走一遍,那边出的是 4:2:0。我这次的 JPG 用 Pillow 11.3.0 和 sharp 0.34.5 存,同一质量下 Pillow、sharp 默认和压缩转换的背景统计一样。Pillow 取质量 75、85、95、98、100 五档,sharp 默认和 mozjpeg:true 各取 75、85、95 三档,4:2:0 和 4:4:4 两种采样各存一遍共 66 个文件。背景真值取抠图蒙版全透明的像素且它们在白底 PNG 里全是 255。亚马逊美国站卖家平台的商品图片指南页(2026-10-23 查看)写主图背景是纯白 RGB 255、255、255。国内平台有没有给出这个数,我没找到公开页面,设阈值前得去各自后台确认。

整图占比和图边三圈都靠不住

最省事的写法是数整张图里三个通道都不低于阈值的像素占多少。Pillow 质量 85、4:2:0 存的 JPG,=255 的占比是毛绒 72.65%、玻璃 75.79%、白鞋 55.25%。≥250 的是 73.43%、76.51%、56.39%。两种写法差 0.7 到 1.1 个百分点,容易让人觉得选哪个都行。但这个占比先取决于背景占多大,三张图之间能差 20 个百分点以上,画不出一条判白的线。我又把三张图的底改成 252 再存一遍。整图 ≥250 的占比是 73.41%、76.46%、56.34%,与纯白底只差 0.02 到 0.05 个百分点。这个指标看不出 252 的底。

只看最外三圈像素不需要蒙版也好写。我数了一遍。要求三圈都是 255,66 个 JPG 里拦下 32 个:白鞋 22 个全拦。玻璃杯拦 10 个,毛绒一个没拦。白鞋有一角贴着图边所以最外圈里本来就有鞋。玻璃杯有 6 个主体像素碰到最外圈。拦下的 10 个是不是它们造成的我没逐个对。改成三圈都 ≥250,66 个全过。可 254 和 252 的底也全过了,6 张一张没拦住。

逐像素等于255会把整批JPG拦下

那就换最严的写法:背景里每个像素都等于 255。66 个 JPG 一个没过。背景按抠图蒙版算总有 0.02% 到 0.7% 的像素不是 255。多数落在 250 到 254,集中在主体边缘。我顺手试了 Pillow 质量 100 加 4:4:4,还剩 0.02% 到 0.05% 的像素不是 255,体积涨到 297 到 692 KB(文中 KB 按 1024 字节算)。这条线放在 PNG 这类无损文件上能用。放在 JPG 上等于永远报警,报警多了就没人看了。

放宽到250会放过近白底

放宽到 250 看上去顺理成章。背景区域里 =255 的占比是 99.34% 到 99.71%。≥250 的占比到了 99.98% 以上。JPG 的杂点几乎全被收进来了。

这张图左边是整图判白的占比,三条线几乎是平的,阈值从 255 放到 240 也只涨一点,说明整图占比判不了什么。右边只看背景区域,三条线从 255 爬到 250 就贴近 100%,说明 250 能容下杂点。可它同样容得下 252。图里照片的作者是 Dan Bollinger、Kritzolina、JustinLiang522,来自维基共享资源。许可是 CC BY-SA 4.0,图是改编作品并沿用同一许可。

我把底改成 254 或 252 的 6 张反例,拿从图边连进来的近白区域里低于 250 的占比去比。反例是 0.21% 到 0.56%,真 JPG 是 0.17% 到 0.50%。两段叠在一起,按 ≥250 数分不开。底改成 250 才拉开一点,是 0.69%、0.68% 和 1.22%。也只在 1% 上下。平台会不会真的拦 252 我不知道,页面只写了 255。我照页面写的数设防,252 过了算漏。

看白区域里255占多少才分得开

绕开阈值的办法是换个问法:不问每个像素够不够白,问图边连进来的那片白里恰好等于 255 的占多少。JPG 的杂点只占一小撮。近白底整片都不是 255。两边差得很远。白区域我定义成三个通道最小值不低于 240 且和图像四边连通的像素。下面是我跑的那段,OpenCV 只用来做连通域。

python 复制代码
import numpy as np, cv2
from PIL import Image

def white_gate(path, floor=240, min_share=0.9):
    low = np.asarray(Image.open(path).convert('RGB')).min(axis=2)
    _, lab = cv2.connectedComponents((low >= floor).astype('uint8'), connectivity=4)
    edge = np.unique(np.concatenate([lab[0], lab[-1], lab[:, 0], lab[:, -1]]))
    reg = np.isin(lab, edge[edge > 0])
    share = (low[reg] == 255).mean() if reg.any() else 0.0
    return share >= min_share, reg.mean(), share

返回的三个值是能不能过、白区域占整图多少、区域里 =255 的占比。我拿它跑了 66 个真 JPG 和 15 张反例。真 JPG 的占比在 97.52% 到 99.40% 且 66 个全过。底改成 254 到 245 的 12 张反例占比最高 0.64%,底改成 238 的三张不到 240。白区域缩成整图的 0% 到 0.26%,占比是 0、18.18%、30.80%。15 张一张没过。最近的反例是 30.80%,最低的真 JPG 是 97.52%,中间隔着一大段。阈值取 0.5、0.9、0.97 时真 JPG 全过、反例全不过。取 0.99 时真 JPG 只过 19 个。原因是白区域比蒙版背景多出 14,987 到 31,464 个像素,都是主体边上同样不低于 240 的亮点。占比被它们拉低,线就不能卡在 99%。

判法 真 JPG(66 个)通过 近白底反例(15 张)通过
最外三圈都是 255 34 0
最外三圈都 ≥250 66 6
白区域每个像素都是 255 0 0
白区域里 =255 的占比 ≥90% 66 0

账也好算。这台 M4 上单张约 28 毫秒,66 张一共 1.8 秒。放在上传前跑一遍成本可以忽略。我一个人做东西最怕检查太严天天误报,最后被自己关掉。所以宁可让线松在 90% 也不去追 99%。

阈值取90还只是推断

能说的只有这批样本:三张维基图、66 个 JPG,编码器是 Pillow 11.3.0 和 sharp 0.34.5。反例是我把背景改成纯色造出来的。渐变底、投影、手拍的图都没测。白区域我没设面积下限,只有一角是白的图会不会被放过我没造这种反例。亚马逊要求商品占图片的 85%。商品占得多白区域就小,这种图也没测。floor 取 230、240、245、250 结果都一样,这一点倒是跑过。

我打算先把 white_gate 接在上传前,只打印占比不拦截再攒一批自己的图看分布。照搬的话我会先看自己那批图占比的最低值,再往下留一截定阈值。不直接套我的 90%。

相关推荐
志尊宝1 小时前
AI原生前端开发(017):端侧AI与Vue 3结合实战
前端·人工智能·prompt·1024·ai-native
特立独行的猫A1 小时前
一份代码,多端产物:仓颉语言的cj-tauri 框架开发桌面和鸿蒙应用指南
前端
代码猎人1 小时前
前端怎么精通Vue3核心原理
前端
不可能片场1 小时前
工程实践 台账备份从全量复制改成增量日志
前端·electron
2603_965896621 小时前
CSS BEM 命名规范|组件化样式分层权威指南
前端·javascript·css
进击的明明1 小时前
前端开发中的 BEM 国际命名规范:让 CSS 不再"打架"
前端·css·html
deli0071 小时前
中文在网址里为什么变成 E4B8AD?URL 编码 22 组用例实测
前端
羲云1 小时前
MOSS-Image 开源后爆火:5B 生图模型真正值得关注的,是可控排版
前端
BreezeJiang1 小时前
闭包和 useState 是两个知识点?你可能只学了半条作用域链
前端·面试