Zajmuję się przetwarzaniem wideo w czasie rzeczywistym na iOS z szybkością 120 klatek na sekundę i chcę najpierw przetworzyć obraz na GPU (pomniejszone, przekonwertowane kolory itp., Które nie są wystarczająco szybko na CPU), a później na postprocessingu na CPU wykorzystującym OpenCV.Przetwarzanie danych z kamery na GPU (metal) i procesorze (OpenCV) na iPhonie
Jaki jest najszybszy sposób udostępnienia kanału z kamery między procesorem graficznym a procesorem za pomocą narzędzia Metal?
Innymi słowy rura będzie wyglądać następująco:
CMSampleBufferRef -> MTLTexture or MTLBuffer -> OpenCV Mat
jestem konwersji CMSampleBufferRef -> MTLTexture następujący sposób
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);
}
}
Po moim metalu shader jest finised przekonwertować MTLTexture do OpenCV
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];
Niektóre obserwacje:
1) Niestety MTLTexture.getBytes
wydaje drogie (Kopiowanie danych z GPU do CPU) i trwa około 5ms na moim iPhone 5S, który jest zbyt dużo przy przetwarzaniu w ~ 100fps
2) Zauważyłem kilka osób? używać MTLBuffer zamiast MTLTexture z następującą metodą: metalDevice.newBufferWithLength(byteCount, options: .StorageModeShared)
(patrz: Memory write performance - GPU CPU Shared Memory)
jednak CMSampleBufferRef
i towarzyszące CVPixelBufferRef
zarządzanego przez corevideo jest przypuszczenie.
Procesor graficzny nie jest obsługiwany we wszystkich rozdzielczościach. Wiem, to nie jest twoja odpowiedź. Po prostu podaję informację o GPU. –
wypróbowałeś GPUImage https://github.com/BradLarson/GPUImage –
Próbowałem GPUImage ale największym bottlenect jest transfer danych z GPU do CPU. GPUImage używa OpenGL pod dobrym i przeciwnym do Metal API nie może mieć współużytkowanej pamięci. – pzo