c++ - Procesamiento de video con OpenCV en el proyecto IOS Swift
video-processing (1)
Esta es una actualización de mi respuesta inicial después de que tuve la oportunidad de jugar con esto yo mismo. Sí, es posible usar CvVideoCamera
con un controlador de vista escrito en Swift. Si solo quieres usarlo para mostrar video de la cámara en tu aplicación, es realmente fácil.
#import <opencv2/highgui/cap_ios.h>
través del encabezado de puente. Luego, en su controlador de vista:
class ViewController: UIViewController, CvVideoCameraDelegate {
...
var myCamera : CvVideoCamera!
override func viewDidLoad() {
...
myCamera = CvVideoCamera(parentView: imageView)
myCamera.delegate = self
...
}
}
ViewController
no puede ajustarse realmente al protocolo CvVideoCameraDelegate
, pero CvVideoCamera
no funcionará sin un delegado, por lo que solucionamos este problema al declarar que ViewController
adopta el protocolo sin implementar ninguno de sus métodos. Esto activará una advertencia del compilador, pero la transmisión de video de la cámara se mostrará en la vista de la imagen.
Por supuesto, es posible que desee implementar el CvVideoCameraDelegate
() de processImage()
para procesar cuadros de video antes de mostrarlos. La razón por la que no puede implementarlo en Swift es porque usa un tipo de C ++, Mat
.
Por lo tanto, deberá escribir una clase Objective-C ++ cuya instancia se puede configurar como delegado de la cámara. El método processImage()
en esa clase Objective-C ++ será llamado por CvVideoCamera
y, a su vez, llamará al código en su clase Swift. Aquí hay algunos ejemplos de fragmentos de código. En OpenCVWrapper.h
:
// Need this ifdef, so the C++ header won''t confuse Swift
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif
// This is a forward declaration; we cannot include *-Swift.h in a header.
@class ViewController;
@interface CvVideoCameraWrapper : NSObject
...
-(id)initWithController:(ViewController*)c andImageView:(UIImageView*)iv;
...
@end
En la implementación del contenedor, OpenCVWrapper.mm
(es una clase Objective-C ++, de ahí la extensión .mm):
#import <opencv2/highgui/cap_ios.h>
using namespace cv;
// Class extension to adopt the delegate protocol
@interface CvVideoCameraWrapper () <CvVideoCameraDelegate>
{
}
@end
@implementation CvVideoCameraWrapper
{
ViewController * viewController;
UIImageView * imageView;
CvVideoCamera * videoCamera;
}
-(id)initWithController:(ViewController*)c andImageView:(UIImageView*)iv
{
viewController = c;
imageView = iv;
videoCamera = [[CvVideoCamera alloc] initWithParentView:imageView];
// ... set up the camera
...
videoCamera.delegate = self;
return self;
}
// This #ifdef ... #endif is not needed except in special situations
#ifdef __cplusplus
- (void)processImage:(Mat&)image
{
// Do some OpenCV stuff with the image
...
}
#endif
...
@end
Luego pones #import "OpenCVWrapper.h"
en el encabezado de puente, y el controlador de vista Swift podría verse así:
class ViewController: UIViewController {
...
var videoCameraWrapper : CvVideoCameraWrapper!
override func viewDidLoad() {
...
self.videoCameraWrapper = CvVideoCameraWrapper(controller:self, andImageView:imageView)
...
}
Consulte https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html sobre las declaraciones directas y la interoperabilidad Swift / C ++ / Objective-C. Hay mucha información en la web sobre #ifdef __cplusplus
y extern "C"
(si la necesita).
En el método delegar processImage()
es probable que necesites interactuar con alguna API OpenCV, para lo cual también deberás escribir wrappers. Puede encontrar información sobre eso en otro lugar, por ejemplo aquí: Usar OpenCV en Swift iOS
He integrado opencv en el proyecto Swift IOS utilizando un encabezado puente (para conectar Swift al Objective C) y un contenedor Objective C (para conectar Objective C a C ++). Usando este método, puedo pasar imágenes individuales del código Swift, analizarlas en los archivos C ++ y recuperarlas.
Pero dado que mi UIViewController está escrito en Swift, me he preguntado si esto también es posible.