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

本文详细介绍了使用Metal进行直方图均衡化的实现过程,包括CPU和GPU的处理方法,遇到的问题及解决方案,例如统计结果集中、CPU-GPU统计差异、渲染为白色等问题,并提供了完整修复后的效果。
摘要由CSDN通过智能技术生成

前言

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 < sourceTexture.get_height())    {  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值