You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中高效统计位图的白色像素数量?

高效白色像素统计优化方案

针对你的实时位图白色像素统计需求,以下是几种比当前分支判断更高效的优化方案:

1. 移除条件分支,利用位运算减少CPU分支预测开销

当前的if-else分支会触发CPU分支预测逻辑,当像素匹配状态波动大时易出现预测失败,拖慢性能。可以改成无分支写法:

var isMatching = distance <= toleranceSquared;
// 统一赋值RGB通道
row[rIndex] = row[bIndex] = row[gIndex] = isMatching ? matchingValue : unmatchingValue;
// 直接将bool转成1/0累加,避免分支
WhitePixelCount += Unsafe.As<bool, byte>(ref isMatching);

.NET中bool类型以byte存储(true=1,false=0),用Unsafe直接转换可避免额外条件判断。

2. 用SIMD批量处理像素(.NET Core 3.0+)

利用.NET的SIMD特性,一次性处理多个像素的距离计算与统计,充分发挥CPU并行计算能力:

// 假设像素数据为BGRA格式,按Vector<float>长度批量处理
var toleranceVec = new Vector<float>(toleranceSquared);
var targetWhiteVec = new Vector<float>(255f);

// 批量读取RGB通道数据
var rVec = new Vector<float>(row.AsSpan(rIndex, Vector<float>.Count));
var gVec = new Vector<float>(row.AsSpan(gIndex, Vector<float>.Count));
var bVec = new Vector<float>(row.AsSpan(bIndex, Vector<float>.Count));

// 批量计算距离平方:(255-R)² + (255-G)² + (255-B)²
var diffR = targetWhiteVec - rVec;
var diffG = targetWhiteVec - gVec;
var diffB = targetWhiteVec - bVec;
var distanceSqVec = diffR * diffR + diffG * diffG + diffB * diffB;

// 批量统计匹配的像素数
var matchMask = Vector.LessThanOrEqual(distanceSqVec, toleranceVec);
WhitePixelCount += (int)Vector.Dot(matchMask, Vector<float>.One);

// 批量赋值RGB通道
var matchValueVec = new Vector<byte>(matchingValue);
var unmatchValueVec = new Vector<byte>(unmatchingValue);
var resultVec = Vector.ConditionalSelect(matchMask, matchValueVec, unmatchValueVec);

resultVec.CopyTo(row.AsSpan(rIndex));
resultVec.CopyTo(row.AsSpan(gIndex));
resultVec.CopyTo(row.AsSpan(bIndex));

SIMD可一次性处理8~16个像素(取决于CPU架构),能将处理速度提升数倍。

3. 跳过像素修改,仅统计数量(如果不需要保留过滤后的位图)

如果核心需求只是对比白色像素数量,不需要输出过滤后的位图,可完全移除像素赋值逻辑,只做统计:

int dr = 255 - row[rIndex];
int dg = 255 - row[gIndex];
int db = 255 - row[bIndex];
if ((dr * dr + dg * dg + db * db) <= toleranceSquared)
{
    WhitePixelCount++;
}

内存写入是相对耗时的操作,跳过这一步能大幅提升统计速度。

4. 用unsafe指针直接操作内存

在unsafe上下文里直接使用byte指针遍历像素数据,避免数组索引的额外开销:

unsafe
{
    fixed (byte* rowPtr = row)
    {
        byte* rPtr = rowPtr + rIndex;
        byte* gPtr = rowPtr + gIndex;
        byte* bPtr = rowPtr + bIndex;
        
        int dr = 255 - *rPtr;
        int dg = 255 - *gPtr;
        int db = 255 - *bPtr;
        int distanceSq = dr * dr + dg * dg + db * db;
        
        if (distanceSq <= toleranceSquared)
        {
            *rPtr = *gPtr = *bPtr = matchingValue;
            WhitePixelCount++;
        }
        else
        {
            *rPtr = *gPtr = *bPtr = unmatchingValue;
        }
    }
}

直接指针操作比数组索引访问效率更高,适合大规模像素处理场景。


内容的提问来源于stack exchange,提问作者Jona4Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 17:55:19