Ich bin ein Bachelor-Student und ich benutze jetzt CoreML Frame, um einige Video HumanSeg App auf dem iPhone zu tun, aber wie der Titel zeigt, habe ich ein Huuuuge Problem .CVPixelBuffer Schreiben mit UIImage.draw() ist zu langsam
Ich habe eine UIImage und ich muss Größe und Pad und es in einen CVPixelBuffer ziehen, um das MobileNet-Modell zu füttern, aber ein solcher Prozess ist einfach zu langsam, kostet etwa 30 ms, was nicht akzeptabel ist.
Um genau zu sein, In meinem Code, Methode UIImage.draw (in: CGRect (X: Int, y: Int, Breite: Int, Höhe: Int)) ist zu langsam, und nahm mich 20+ ms, die ist das Hauptproblem.
Meine Codes sind unten:
func dealRawImage(image : UIImage, dstshape : [Int], pad : UIImage) -> CVPixelBuffer?
{
// decide whether to shrink in height or width
let height = image.size.height
let width = image.size.width
let ratio = width/height
let dst_width = Int(min(CGFloat(dstshape[1]) * ratio, CGFloat(dstshape[0])))
let dst_height = Int(min(CGFloat(dstshape[0])/ratio, CGFloat(dstshape[1])))
let origin = [Int((dstshape[0] - dst_height)/2), Int((dstshape[1] - dst_width)/2)]
// init a pixelBuffer to store the resized & padded image
var pixelBuffer: CVPixelBuffer?
let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue]
CVPixelBufferCreate(kCFAllocatorDefault,
dstshape[1],
dstshape[0],
kCVPixelFormatType_32ARGB,
attrs as CFDictionary,
&pixelBuffer)
// get the pointer of this pixelBuffer
CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
// init a context that contains this pixelBuffer to draw in
let context = CGContext(data: pixelData,
width: dstshape[1],
height: dstshape[0],
bitsPerComponent: 8,
bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!),
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)!
// push context
UIGraphicsPushContext(context)
context.translateBy(x: 0, y: CGFloat(dstshape[0]))
context.scaleBy(x: 1, y: -1)
pad.draw(in:CGRect(x: 0, y: 0, width: dstshape[1], height: dstshape[0]))
// THIS SINGLE FUNCTION COSTS ME 20+ ms AND IS THE MAJOR ISSUE !
image.draw(in: CGRect(x: origin[1], y: origin[0], width: dst_width, height: dst_height))
UIGraphicsPopContext()
// unlock
CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
return pixelBuffer
}
Und ich rufe einfach diese Funktion wie folgt aus:
let input = dealRawImage(image: raw_input_image, dstshape: [224, 224], pad: black_image)
Wo raw_input_image die UIImage I aus dem Speicher gelesen, dstshape ist die Form, die ich möchte, um die Größe Dieses Bild zu, und Black_image ist eine völlig schwarze UIImage zum Auffüllen verwendet.
Ich habe auf dieser Website gesucht, aber kein bekanntes Problem gefunden.
Gibt es eine Möglichkeit, diesen Prozess schneller zu machen und dieses Projekt zu speichern? Ich möchte meine zweiwöchige Arbeit einfach nicht aufgeben.
Ich bin nicht sicher, warum die Zeile mit 'image.draw()' ist so viel langsamer als 'pad.draw()' [möglicherweise wegen der Größenänderung] aber zwei Fragen in den Sinn kommen hier: 1) warum Sie müssen auf das Eingabebild padding? 2) Wenn Sie Geschwindigkeit brauchen, warum sind Ihre Eingabedaten in einem UIImage? –
Oh, eine Sache, die ich versuchen würde, macht 'image.draw()' verwenden 0, 0 und die volle Breite und Höhe, und sehen, ob das schneller ist. –
Danke. Und lassen Sie mich zuerst Ihre Fragen beantworten. 1) Ich habe das trainierte MoblieNet-Modell aus meinem Labor bekommen, und meine Senioren haben beim Training dieses Modells die schwarze Polsterung zum Bild gemacht, also muss ich das auch machen, damit dieses Netz korrekt läuft. 2) Ich bin nicht sicher, was ich verwenden kann, wenn ich Bilder von iPhone Kamera oder Album auswählen muss. Ich habe auch versucht, opencv-swift zu benutzen, aber da war etwas nicht in Ordnung und ich kam am Ende zu UIImage zurück. 3) Meinst du, dass die Verwendung anderer Bildformate einen CVPixelBuffer schneller erzeugen kann? – AXIHIXA