web-dev-qa-db-fra.com

Comment convertir un UIImage en CVPixelBuffer

Le nouveau framework CoreML d'Apple a une fonction de prédiction qui prend un CVPixelBuffer. Afin de classer un UIImage une conversion doit être effectuée entre les deux.

Code de conversion que j'ai obtenu d'un ingénieur Apple Engineer:

1  // image has been defined earlier
2
3     var pixelbuffer: CVPixelBuffer? = nil
4   
5     CVPixelBufferCreate(kCFAllocatorDefault, Int(image.size.width), Int(image.size.height), kCVPixelFormatType_OneComponent8, nil, &pixelbuffer)
6     CVPixelBufferLockBaseAddress(pixelbuffer!, CVPixelBufferLockFlags(rawValue:0))
7   
8     let colorspace = CGColorSpaceCreateDeviceGray()
9     let bitmapContext = CGContext(data: CVPixelBufferGetBaseAddress(pixelbuffer!), width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelbuffer!), space: colorspace, bitmapInfo: 0)!
10  
11    bitmapContext.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))

Cette solution est en Swift et est pour une image en niveaux de gris. Les changements qui doivent être effectués en fonction du type d'image sont:

  • Ligne 5 | kCVPixelFormatType_OneComponent8 vers un autre OSType (kCVPixelFormatType_32ARGB pour RVB)
  • Ligne 8 | colorSpace vers un autre CGColorSpace (CGColorSpaceCreateDeviceRGB pour RGB)
  • Ligne 9 | bitsPerComponent au nombre de bits par pixel de mémoire (32 pour RGB)
  • Ligne 9 | bitmapInfo vers une propriété non nulle CGBitmapInfo (kCGBitmapByteOrderDefault est la valeur par défaut)
17
Ryan

Vous pouvez jeter un œil à ce tutoriel https://www.hackingwithswift.com/whats-new-in-ios-11 , le code est en Swift 4

func buffer(from image: UIImage) -> CVPixelBuffer? {
  let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
  var pixelBuffer : CVPixelBuffer?
  let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(image.size.width), Int(image.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
  guard (status == kCVReturnSuccess) else {
    return nil
  }

  CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
  let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)

  let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
  let context = CGContext(data: pixelData, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)

  context?.translateBy(x: 0, y: image.size.height)
  context?.scaleBy(x: 1.0, y: -1.0)

  UIGraphicsPushContext(context!)
  image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
  UIGraphicsPopContext()
  CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))

  return pixelBuffer
}
27
onmyway133