我希望从AVCaptureVideoDataOutput的整个图像中获取平均像素值,目前我正在捕获图像并循环遍历像素进行求和。
我在想是否有更有效的方法使用GPU / openGL来完成此任务,因为这是可并行化的图像处理任务。(也许是重度高斯模糊,并读取中心像素值?)
一个具体的要求是需要高精度的结果,利用高水平的平均值。请注意下面的CGFloat结果。
当前Swift 2代码:
编辑:根据Simon的建议,添加了使用CIAreaAverage的实现。它由
我在想是否有更有效的方法使用GPU / openGL来完成此任务,因为这是可并行化的图像处理任务。(也许是重度高斯模糊,并读取中心像素值?)
一个具体的要求是需要高精度的结果,利用高水平的平均值。请注意下面的CGFloat结果。
当前Swift 2代码:
编辑:根据Simon的建议,添加了使用CIAreaAverage的实现。它由
useGPU
bool分隔。func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
var redmean:CGFloat = 0.0;
var greenmean:CGFloat = 0.0;
var bluemean:CGFloat = 0.0;
if (useGPU) {
let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
let cameraImage = CIImage(CVPixelBuffer: pixelBuffer!)
let filter = CIFilter(name: "CIAreaAverage")
filter!.setValue(cameraImage, forKey: kCIInputImageKey)
let outputImage = filter!.valueForKey(kCIOutputImageKey) as! CIImage!
let ctx = CIContext(options:nil)
let cgImage = ctx.createCGImage(outputImage, fromRect:outputImage.extent)
let rawData:NSData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage))!
let pixels = UnsafePointer<UInt8>(rawData.bytes)
let bytes = UnsafeBufferPointer<UInt8>(start:pixels, count:rawData.length)
var BGRA_index = 0
for pixel in UnsafeBufferPointer(start: bytes.baseAddress, count: bytes.count) {
switch BGRA_index {
case 0:
bluemean = CGFloat (pixel)
case 1:
greenmean = CGFloat (pixel)
case 2:
redmean = CGFloat (pixel)
case 3:
break
default:
break
}
BGRA_index++
}
} else {
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
CVPixelBufferLockBaseAddress(imageBuffer!, 0)
let baseAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer!, 0)
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
let width = CVPixelBufferGetWidth(imageBuffer!)
let height = CVPixelBufferGetHeight(imageBuffer!)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue).rawValue | CGBitmapInfo.ByteOrder32Little.rawValue
let context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, bitmapInfo)
let imageRef = CGBitmapContextCreateImage(context)
CVPixelBufferUnlockBaseAddress(imageBuffer!, 0)
let data:NSData = CGDataProviderCopyData(CGImageGetDataProvider(imageRef))!
let pixels = UnsafePointer<UInt8>(data.bytes)
let bytes = UnsafeBufferPointer<UInt8>(start:pixels, count:data.length)
var redsum:CGFloat = 0
var greensum:CGFloat = 0
var bluesum:CGFloat = 0
var BGRA_index = 0
for pixel in UnsafeBufferPointer(start: bytes.baseAddress, count: bytes.count) {
switch BGRA_index {
case 0:
bluesum += CGFloat (pixel)
case 1:
greensum += CGFloat (pixel)
case 2:
redsum += CGFloat (pixel)
case 3:
//alphasum += UInt64(pixel)
break
default:
break
}
BGRA_index += 1
if BGRA_index == 4 { BGRA_index = 0 }
}
redmean = redsum / CGFloat(bytes.count)
greenmean = greensum / CGFloat(bytes.count)
bluemean = bluesum / CGFloat(bytes.count)
}
print("R:\(redmean) G:\(greenmean) B:\(bluemean)")