2016-05-24 18 views
5

Ho integrato opencv nel progetto IOS di Swift usando l'intestazione di bridging (per collegare Swift a Objective C) e un wrapper Objective C (per connettere l'Objective C al C++). Usando questo metodo posso passare singole immagini dal codice Swift, analizzarle nei file C++ e recuperarle.Elaborazione video con OpenCV nel progetto IOS Swift

I've seen that opencv provides CvVideoCamera object that can be integrated with an Objective C UIViewController.

Ma dal momento che il mio UIViewController sono scritti in Swift mi sono chiesto se questo è possibile pure?

risposta

15

Questo è un aggiornamento della mia risposta iniziale dopo aver avuto la possibilità di giocare con questo me stesso. Sì, è possibile utilizzare CvVideoCamera con un controller di visualizzazione scritto in Swift. Se vuoi solo usarlo per visualizzare i video dalla fotocamera nella tua app, è davvero facile.

#import <opencv2/highgui/cap_ios.h> tramite la testata di collegamento. Poi, nel vostro controller della vista:

class ViewController: UIViewController, CvVideoCameraDelegate { 
... 
    var myCamera : CvVideoCamera! 
    override func viewDidLoad() { 
     ... 
     myCamera = CvVideoCamera(parentView: imageView) 
     myCamera.delegate = self 
     ... 
    } 
} 

Il ViewController non può di fatto conforme al protocollo CvVideoCameraDelegate, ma CvVideoCamera non funzionerà senza un delegato, in modo da ovviare a questo problema, dichiarando ViewController di adottare il protocollo senza attuare alcuna dei suoi metodi. Ciò attiverà un avvertimento del compilatore, ma il flusso video dalla telecamera verrà visualizzato nella vista dell'immagine.

Naturalmente, si potrebbe voler implementare il metodo (solo) processImage() per elaborare i frame video prima di visualizzarli. Il motivo per cui non è possibile implementarlo in Swift è perché utilizza un tipo C++, Mat.

Quindi, sarà necessario scrivere una classe Objective-C++ la cui istanza può essere impostata come delegato della telecamera. Il metodo processImage() in quella classe Objective-C++ verrà chiamato da CvVideoCamera e chiamerà a turno il codice nella classe Swift. Ecco alcuni snippet di codice di esempio. In 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 

Nell'implementazione involucro, OpenCVWrapper.mm (è un-C Obiettivo ++ classe, quindi l'estensione .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 

Poi si mette #import "OpenCVWrapper.h" nell'intestazione ponte, e Swift controller della vista potrebbe essere simile a questo:

class ViewController: UIViewController { 
... 
    var videoCameraWrapper : CvVideoCameraWrapper! 

    override func viewDidLoad() { 
     ... 
     self.videoCameraWrapper = CvVideoCameraWrapper(controller:self, andImageView:imageView) 
     ... 
    } 

Vedi https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html su decl avanti arations e interoperabilità Swift/C++/Objective-C. Ci sono molte informazioni sul web su #ifdef __cplusplus e extern "C" (se ne hai bisogno).

Nel metodo delegato processImage() è probabile che sia necessario interagire con alcune API OpenCV, per le quali sarà necessario scrivere anche wrapper. È possibile trovare alcune informazioni su questo altrove, ad esempio qui: Using OpenCV in Swift iOS

+0

Ottenere qualche errore. Puoi fornire entrambi i file –