Я работаю над простым шумоподавляющим PO C в SwiftUI, где я хочу:
- Загрузка входного изображения
- Применение модели CoreML (шумоподавления) к входу image
- Отображение выходного изображения
У меня есть кое-что работающее на основе десятков исходных кодов, которые я нашел в Интернете. Основываясь на том, что я прочитал, модель CoreML (по крайней мере та, которую я использую) принимает CVPixelBuffer и выводит также CVPixelBuffer. Поэтому моя идея заключалась в следующем:
- Преобразование входного UIImage в CVPixelBuffer
- Применение модели CoreML к CVPixelBuffer
- Преобразование недавно созданного CVPixelBuffer в UIImage
(Обратите внимание, что я читал, что с помощью фреймворка Vision можно напрямую ввести CGImage в модель. Я попробую этот подход, как только узнаю, что я Я пытаюсь достичь этого, так как считаю, что это хорошее упражнение.)
Вначале я хотел пропустить шаг (2), чтобы сосредоточиться на проблеме конверсии. В приведенном ниже коде я попытался добиться:
- Преобразование входного UIImage в CVPixelBuffer
- Преобразование CVPixelBuffer в UIImage
I ' Я не Swift или Objective- C разработчик, поэтому я почти уверен, что допустил хотя бы несколько ошибок. Я нашел этот код довольно сложным, и мне было интересно, есть ли лучший / более простой способ сделать то же самое?
func convert(input: UIImage) -> UIImage? {
// Input CGImage
guard let cgInput = input.cgImage else {
return nil
}
// Image size
let width = cgInput.width
let height = cgInput.height
let region = CGRect(x: 0, y: 0, width: width, height: height)
// Attributes needed to create the CVPixelBuffer
let attributes = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue]
// Create the input CVPixelBuffer
var pbInput:CVPixelBuffer? = nil
let status = CVPixelBufferCreate(kCFAllocatorDefault,
width,
height,
kCVPixelFormatType_32ARGB,
attributes as CFDictionary,
&pbInput)
// Sanity check
if status != kCVReturnSuccess {
return nil
}
// Fill the input CVPixelBuffer with the content of the input CGImage
CVPixelBufferLockBaseAddress(pbInput!, CVPixelBufferLockFlags(rawValue: 0))
guard let context = CGContext(data: CVPixelBufferGetBaseAddress(pbInput!),
width: width,
height: height,
bitsPerComponent: cgInput.bitsPerComponent,
bytesPerRow: cgInput.bytesPerRow,
space: cgInput.colorSpace!,
bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) else {
return nil
}
context.draw(cgInput, in: region)
CVPixelBufferUnlockBaseAddress(pbInput!, CVPixelBufferLockFlags(rawValue: 0))
// Create the output CGImage
let ciOutput = CIImage(cvPixelBuffer: pbInput!)
let temporaryContext = CIContext(options: nil)
guard let cgOutput = temporaryContext.createCGImage(ciOutput, from: region) else {
return nil
}
// Create and return the output UIImage
return UIImage(cgImage: cgOutput)
}
Когда я использовал этот код в своем проекте SwiftUI, входные и выходные изображения выглядели одинаково , но не было одинаковых. Я думаю, что входное изображение было связано с картой цветов (ColorSyn c Profile), которая была потеряна во время преобразования. Я предполагал, что должен был использовать cgInput.colorSpace
во время создания CGContext, но казалось, что использование CGColorSpace(name: CGColorSpace.sRGB)!
работало лучше. Может кто-нибудь объяснить мне это?
Спасибо за вашу помощь.