Получить яркость пикселей из необработанных данных изображения - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь получить среднее значение яркости / яркости фото с помощью фреймворка 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

...