前言
Metal入门教程总结
正文
核心思路
首先,我们用直方图来表示一张图像:横坐标代表的是颜色值,纵坐标代表的是该颜色值在图像中出现次数。

如图,对于某些图像,可能出现颜色值集中分布在某个区间的情况。
直方图均衡化(Histogram Equalization) ,指的是对图像的颜色值进行重新分配,使得颜色值的分布更加均匀。
本文用compute shader对图像的颜色值进行统计,然后计算得出映射关系,由fragment shader进行颜色映射处理。
效果展示
具体步骤
1、Metal的render管道、compute管道配置;
同前文,不再赘述,详见Metal入门教程总结。
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 sourceTexture [[textureLYKernelTextureIndexSource]], // 纹理输入, device LYColorBuffer &out [[buffer(LYKernelBufferIndexOutput)]], // 输出的buffer uint2 grid [[thread_position_in_grid]]) // 格子索引{ // 边界保护 if(grid.x < sourceTexture.get_width() && grid.y

本文详细介绍了使用Metal进行直方图均衡化的实现过程,包括CPU和GPU的处理方法,遇到的问题及解决方案,例如统计结果集中、CPU-GPU统计差异、渲染为白色等问题,并提供了完整修复后的效果。
最低0.47元/天 解锁文章
2063

被折叠的 条评论
为什么被折叠?



