Сохранение данных глубины (с 16-битной глубиной) в качестве вспомогательных данных в файле JPEG

Я хочу иметь возможность хранить данные глубины захваченного кадра ARframe в iOS в файле со сжатием без потерь.

Согласно этому докладу WWDC:

«В iOS 11 мы поддерживаем два типа изображений с глубиной. Первый - это HEIF HEVC, новый формат, также называемый файлами HEIC, и там первоклассная поддержка глубины ... Второй поддерживаемый нами формат - это JPEG. Боже, JPEG не предназначался для подобных трюков, но мы все равно сделали этот трюк. Карта представляет собой 8-битный JPEG с потерями, если он отфильтрован, или если в нем нет чисел, мы используем 16-битный JPEG без потерь. Кодирование JPEG, чтобы сохранить все не числа, и мы храним его как второе изображение внизу JPEG, так что это похоже на объект с несколькими изображениями, если вы знакомы с этим ».

Когда я сравниваю исходный буфер глубины (16-битный) с буфером глубины, который я извлекаю из сохраненного изображения по пикселям, я получаю следующие результаты:

First Second 0.61865234 0.6196289 0.62109375 0.6196289 0.6269531 0.6274414 0.6298828 0.63134766 0.6328125 0.63134766 nan 0.003921509 nan 0.0 nan 0.0 nan 0.007843018 nan 0.003921509

Даже когда у меня есть нефильтрованные данные глубины с NAN в них, сохраненные данные не могут их сохранить, и при этом они не используют кодирование без потерь, как кажется.

Это код, который я написал:

if let currentFrame = session.currentFrame, let depthData = currentFrame.capturedDepthData { // The session variable is an ARSession object  
        let outputURL: URL? = filePath(forKey: "test")
        guard let cgImageDestination = CGImageDestinationCreateWithURL(outputURL! as CFURL, kUTTypeJPEG, 1, nil) else {
            return
        }

        depthData.depthDataMap.normalize() // Normalizing depth data between 0.0 and 1.0
        let sixteenBitDepthData = depthData.converting(toDepthDataType: kCVPixelFormatType_DepthFloat16)

        let ciImage = CIImage(cvPixelBuffer: currentFrame.capturedImage)
        let context = CIContext(options: nil)
        let dict: NSDictionary = [
            kCGImageDestinationLossyCompressionQuality: 1.0,
            kCGImagePropertyIsFloat: kCFBooleanTrue,
        ]
        if let cgImage: CGImage = context.createCGImage(ciImage, from: ciImage.extent) {
            CGImageDestinationAddImage(cgImageDestination, cgImage, nil)
        }

        var auxDataType: NSString?
        let auxData = sixteenBitDepthData.dictionaryRepresentation(forAuxiliaryDataType: &auxDataType)
        CGImageDestinationAddAuxiliaryDataInfo(cgImageDestination, auxDataType!, auxData! as CFDictionary)

        CGImageDestinationFinalize(cgImageDestination)

        if let second = getDepthBufferFromFile(key: "test") {
            self.compareBuffers(first: sixteenBitDepthData.depthDataMap, second: second)
        }
    }

person Dhruv Pargai    schedule 07.10.2019    source источник
comment
У меня была такая же проблема. Я пробовал сохранять вспомогательную глубину как в форматах JPEG, так и в HEIC, и ни в том, ни в другом случае не выглядел без потерь. Хотел бы получить четкий ответ на этот вопрос.   -  person miweinst    schedule 07.10.2019


Ответы (1)


Природа JPEG файла делает ваши испытания бессмысленными. iOS поддерживает 8-битные 3-канальные JPEG или 16-битные 8-канальные JPEG. Однако форматы файлов, позволяющие хранить истинную информацию о глубине, такие как файл без потерь OpenEXR, поддерживают 32-битные данные цвета внутри 1023 каналов. Такая глубина цвета необходима для сохранения стабильной глубины сцены. Такое количество каналов необходимо для хранения дополнительных полезных каналов.

Итак, на мой взгляд, самое простое решение в вашем случае - использовать 32-битный несжатый или сжатый файл EXR для хранения глубины, альфа, диспаратности, движения и других каналов, а не 16-битный файл JPEG, сделанный вручную Apple.

person Andy Fedoroff    schedule 25.10.2020