Я пытаюсь получить среднее значение яркости / яркости фото с помощью фреймворка AVFoundation. То, что я делаю, - это получение пиксельного буфера (который поставляется только с захватом RAW) из объекта AVCapturePhoto, доступ к его пикселям с помощью UnsafeMutablePointer и получение значения яркости в определенной точке. Среднее значение, которое я ожидаю получить, должно быть между 528 и 4095 (уровни черного и белого). Я не уверен, какое значение я получу из этого буфера и правильно ли я получаю доступ к его пикселям. Я также не уверен, что это лучший подход, но значение зеленого, которое я получаю из самого изображения, кажется сжатым, так как оно никогда не превышает 255.
Ниже приведен код, который я использую:
// The pixel buffer stores an image in main memory.
let pixelBuffer = photo.pixelBuffer!
// Locks the BaseAddress of the PixelBuffer to ensure that the memory is accessible.
CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
// Buffer width and height
let bufferWidth = CVPixelBufferGetWidth(pixelBuffer) // 4032
let bufferHeight = CVPixelBufferGetHeight(pixelBuffer) // 3024
/*
Returns the base address of the PixelBuffer.
Retrieving the base address for a PixelBuffer requires that the buffer base address be locked via a successful call to CVPixelBufferLockBaseAddress.
*/
let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer)
let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer) // 8064
/*
Returns the bits of the given instance, interpreted as having the specified type.
Use this function only to convert the instance passed as x to a layout-compatible type when conversion through other means is not possible.
*/
let pointer = unsafeBitCast(pixelBuffer, to: UnsafeMutablePointer<UInt16>.self) // what data type to use?
//let pointer = baseAddress?.bindMemory(to: UInt16.self, capacity: CVPixelBufferGetDataSize(pixelBuffer))
var lumaSum: Double = 0.0
for y in 0..<bufferHeight {
for x in 0..<bufferWidth {
let index = y * bufferWidth + x // or y * bytesPerRow + x
let luma = Double(pointer[index])
lumaSum += luma
}
}
let average = lumaSum / Double(bufferWidth * bufferHeight)
print(average)
CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
Вот некоторая информация, которая может быть полезна:
Пиксельный формат: kCVPixelFormatType_14Bayer_RGGB = 'rgg4', / * 14-битный байерский байтер Little-Endian, упакованный в 16-битные, упорядоченный R G R G ... чередующийся с G B G B ... * /
Размер данных буфера: 24385600
Содержит RGB: true
Биты на компонент: 8
байт в строке: 8064
бит за блок: 16