2017-06-09 12 views
11

में कनवर्ट करने के लिए कैसे करें Apple के नए CoreML ढांचे में भविष्यवाणी फ़ंक्शन है जो CVPixelBuffer लेता है। UIImage वर्गीकृत करने के लिए दोनों के बीच एक रूपांतरण किया जाना चाहिए।UIImage को एक CVPixelBuffer

रूपांतरण कोड मैं एक एप्पल इंजीनियर से मिला:

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)) 

यह समाधान तेजी में है और एक ग्रेस्केल छवि के लिए है। छवि के प्रकार के आधार पर किए गए परिवर्तन हैं:

  • रेखा 5 | kCVPixelFormatType_OneComponent8 अन्य OSType (kCVPixelFormatType_32ARGB आरजीबी के लिए)
  • लाइन 8 | colorSpace अन्य CGColorSpace (CGColorSpaceCreateDeviceRGB आरजीबी के लिए)
  • लाइन 9 | bitsPerComponent बिट्स प्रति पिक्सेल की बिट्स (आरजीबी के लिए 32)
  • लाइन 9 | bitmapInfo एक अशून्य CGBitmapInfo संपत्ति के लिए,
+0

मुझे लगता है कि में है 'CVPixelBuffer' बस छवियों के लिए एक सम्मेलन है कैमरे से, 'ciImage' भी उपलब्ध है, 'cgImage' उपलब्ध – WeiJay

+0

विजन फ्रेमवर्क का उपयोग क्यों नहीं करें? आप (1) एक 'VNCoreMLModel' ऑब्जेक्ट प्रारंभ कर सकते हैं, फिर एक पूर्णांक हैंडलर के साथ एक (2) 'VNCoreMLRequest', फिर एक (3)' VNImageRequestHandler' का उपयोग करें - जो' CIImage' या फ़ाइल URL ले सकता है। परिणाम 'VNClassificationObservation' ऑब्जेक्ट्स का संग्रह हैं। अब निश्चित रूप से, यदि आप 'UIImage' को' CVPixelBuffer' में कनवर्ट करना चाहते हैं - जिसे आपने वास्तव में ** ** कहीं भी नहीं कहा ** ** आपके प्रश्न के बारे में कोई प्रश्न नहीं था :-) - आप बस इसके लिए इंटरनेट खोज सकते हैं और इसे ढूंढ सकते हैं: https://gist.github.com/cieslak/743f9321834c5a40597afa1634a48343 – dfd

+0

@dfd हाँ इसलिए मैं कोरम का उपयोग करने के प्रयोजनों के लिए 'UIImage' को' CVPixelBuffer' में परिवर्तित करना चाहता था मॉडल, लेकिन मुझे इस समस्या को उपरोक्त कोड के साथ डब्ल्यूडब्ल्यूडीसी में एक ऐप्पल इंजीनियर द्वारा हल किया गया था। यह देखते हुए कि सम्मेलन में कई अन्य लोगों के पास एक ही समस्या है, मुझे लगा कि मैं उस समाधान को साझा करूंगा जो उस उद्देश्य को जीथब समाधान की तुलना में अधिक सादगी के साथ प्राप्त करता है। सुझावों के लिए धन्यवाद! – Ryan

उत्तर

14

आप इस ट्यूटोरियल https://www.hackingwithswift.com/whats-new-in-ios-11 पर एक नज़र ले जा सकते हैं (kCGBitmapByteOrderDefault डिफ़ॉल्ट है) कोड स्विफ्ट 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 
}