Ich mache Echtzeit-Video-Verarbeitung auf iOS mit 120 fps und will zuerst Bild auf GPU (Downsample, konvertieren Farbe, etc., die nicht sind schnell genug auf der CPU) und später den Frame auf der CPU mit OpenCV nachbearbeiten.Processing Kamera Feed-Daten auf GPU (Metall) und CPU (OpenCV) auf iPhone
Was ist der schnellste Weg, Kamera Feed zwischen GPU und CPU mit Metal zu teilen?
Mit anderen Worten: das Rohr aussehen würde:
CMSampleBufferRef -> MTLTexture or MTLBuffer -> OpenCV Mat
I CMSampleBufferRef bin Umwandlung -> MTLTexture die folgende Art und Weise
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// textureRGBA
{
size_t width = CVPixelBufferGetWidth(pixelBuffer);
size_t height = CVPixelBufferGetHeight(pixelBuffer);
MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;
CVMetalTextureRef texture = NULL;
CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &texture);
if(status == kCVReturnSuccess) {
textureBGRA = CVMetalTextureGetTexture(texture);
CFRelease(texture);
}
}
Nach meinem Metall-Shader ich konvertieren MTLTexture zu OpenCV finised ist
cv::Mat image;
...
CGSize imageSize = CGSizeMake(drawable.texture.width, drawable.texture.height);
int imageByteCount = int(imageSize.width * imageSize.height * 4);
int mbytesPerRow = 4 * int(imageSize.width);
MTLRegion region = MTLRegionMake2D(0, 0, int(imageSize.width), int(imageSize.height));
CGSize resSize = CGSizeMake(drawable.texture.width, drawable.texture.height);
[drawable.texture getBytes:image.data bytesPerRow:mbytesPerRow fromRegion:region mipmapLevel:0];
Einige Beobachtungen:
1) Leider MTLTexture.getBytes
scheint teuer (das Kopieren von Daten von GPU CPU) und dauert etwa 5 ms auf meinem iPhone 5S, das zu viel ist, wenn die Verarbeitung bei ~ 100fps
2) ich einige Leute bemerkt? verwendet MTLBuffer statt MTLTexture mit folgenden Methode: metalDevice.newBufferWithLength(byteCount, options: .StorageModeShared)
(siehe: Memory write performance - GPU CPU Shared Memory)
jedoch CMSampleBufferRef
und begleitende CVPixelBufferRef
wird von Corevideo ist zu erraten.
Die GPU wird nicht für alle Auflösungen unterstützt. Ich weiß, es ist nicht deine Antwort. Ich gebe nur eine Information über GPU. –
haben Sie versucht GPUImage https://github.com/BradLarson/GPUImage –
Ich versuchte GPUImage, aber der größte Engpass ist die Übertragung von Daten von der GPU zur CPU. GPUImage verwendet OpenGL unter der guten und gegenüber der Metal-API kann keinen gemeinsamen Speicher haben. – pzo