Swift图像直方图

本文介绍了如何使用Swift和Metal框架在GPU上计算并绘制图像直方图。首先解释了图像直方图的概念,然后详细阐述了利用RGBA格式处理图像数据,以及通过CPU实现直方图计算的不足。接着,文章探讨了GPU计算的优势,详细讲解了MTLDevice、MTLCommandQueue、MTLLibrary等Metal组件的使用,以及如何编写和配置计算管线与Shader函数,以实现高效、并发的直方图计算。最后,提到了计算完成后绘制直方图的过程。
摘要由CSDN通过智能技术生成

最近公司项目需求需要绘制出来图像的直方图,所以近期研究了一下。

图像的直方图是什么?

图像的直方图跟图像的亮度有很大关系。图像的亮度可以分为0-255个数值,不同的值代表不同的亮度,0代表纯黑色的黑暗区域,255表示最亮的纯白色区域。以亮度作为横轴,图像在不同的亮度下包含的像素的个数作为纵轴得到的图像就是图像的直方图。

有的童鞋想深入了解一下图像的直方图,可以看一下这篇 文章,这里不做过多赘述。

RGBA格式

RGB以R(Red,红色), G(Green,绿色),B(Blue,蓝色)三种基本颜色来通过不同程度的叠加来获取不同的颜色,我们使用RGBA的格式来组织图像的像素,所以一个像素是由4个byte组成的,分别是R,G,B,A,每一个分量都是由一个byte组成,所以每个分量的取值范围是[0,255]。本来我想的是使用CPU来遍历所有的像素,并把每个像素的R值的亮度,G的亮度,B的亮度,L(Luma)的亮度,并把计算这个数据的个数保存到四个256大小的数组中。当我得到一个图片的时候,我脑海中的第一个想法是把图像以RGBA的格式保存到一个Data中。

CPU

	let context = CIContext()
	let bytesPerRow = Int(image.extent.width) * 4
    let bytesPointer = UnsafeMutableRawPointer.allocate(byteCount: bytesPerRow * Int(image.extent.height), alignment: 4)
  context.render(image, toBitmap: bytesPointer, rowBytes: bytesPerRow, bounds: image.extent, format: .RGBA8, colorSpace: CGColorSpace(name: CGColorSpace.sRGB))
    let pixelData = Data(bytes: bytesPointer, count: bytesPerRow * Int(image.extent.height))
	//不要忘记销毁bytesPointer指向的空间
  bytesPointer.deallocate()      

然后把这个Data按照Uint8的格式进行解码保存到一个数组中,

let allBytes = [Uint8](pixelData)

最后遍历这个数组,生成我们需要的直方图的数据。

//保存[0-255]个亮度上所包含的Red的个数,用于绘制图像直方图
var red:[UInt32] = [UInt32](repeating: 0, count: 256)
//保存[0-255]个亮度上所包含的Green的个数,用于绘制图像直方图
var green:[UInt32] = [UInt32](repeating: 0, count: 256)
//保存[0-255]个亮度上所包含的Blue的个数,用于绘制图像直方图
var blue:[UInt32] = [UInt32](repeating: 0, count: 256)
//保存[0-255]个亮度上所包含的Luma的个数,用于绘制图像直方图
var luma:[UInt32] = [UInt32](repeating: 0, count: 256)

// 4个字节是表示一个像素
for i in 0..<allBytes.count where i % 4 == 0 {
   
            var red   =
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值