直方图均衡化_Metal图像处理——直方图均衡化

本文介绍了如何使用Metal进行直方图均衡化处理,包括CPU和GPU的处理步骤,以及在处理过程中遇到的统计结果不准确、渲染为白色等问题的解决方法。通过compute shader进行颜色统计和映射关系计算,最终实现图像颜色分布的均衡化。
摘要由CSDN通过智能技术生成

核心思路

首先,我们用直方图来表示一张图像:横坐标代表的是颜色值,纵坐标代表的是该颜色值在图像中出现次数。

17ac7a1af77605e7c2afb4c4784e785f.png

如图,对于某些图像,可能出现颜色值集中分布在某个区间的情况。


直方图均衡化(Histogram Equalization) ,指的是对图像的颜色值进行重新分配,使得颜色值的分布更加均匀。

本文用compute shader对图像的颜色值进行统计,然后计算得出映射关系,由fragment shader进行颜色映射处理。

效果展示

1fa68d242d2841e8a73bf82ae64af724.png

具体步骤

1、Metal的render管道、compute管道配置;

2、CPU进行直方图均衡化处理;

2.1 把UIImage转成Bytes;

2.2 颜色统计;

// CPU进行统计
Byte *color = (Byte *)spriteData; for (int i = 0; i < width * height; ++i) { for (int j = 0; j < LY_CHANNEL_NUM; ++j) {
uint c = color[i * 4 + j];
++cpuColorBuffer.channel[j][c];
}
}

2.3 映射关系;

int rgb[3][LY_CHANNEL_SIZE], sum = (int)(width * height); int val[3] = {0}; // 颜色映射
for (int i = 0; i < 3; ++i) { for (int j = 0; j < LY_CHANNEL_SIZE; ++j) {
val[i] += cpuColorBuffer.channel[i][j];
rgb[i][j] = val[i] * 1.0 * (LY_CHANNEL_SIZE - 1) / sum;
}
}

2.4 颜色值修改;

// 值修改
for (int i = 0; i < width * height; ++i) { for (int j = 0; j < LY_CHANNEL_NUM; ++j) {
uint c = color[i * 4 + j];
color[i * 4 + j] = rgb[j][c];
}
}

最后用处理之后的Bytes生成新图片。

3 GPU进行直方图均衡化处理;

3.1 compute shader进行颜色统计;

kernel voidgrayKernel(texture2d<float, access::read> sourceTexture [[textureLYKernelTextureIndexSource]], // 纹理输入,
device LYColorBuffer &out [[buffer(LYKernelBufferIndexOutput)]], // 输出的buffer
uint2 grid [[thread_position_in_grid]]) // 格子索引{ // 边界保护
if(grid.x < sourceTexture.get_width() && grid.y < sourceTexture.get_height())
{
float4 color = sourceTexture.read(grid); // 初始颜色
int3 rgb = int3(color.rgb * SIZE); // 乘以SIZE,得到

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值