这是我有机会自己玩这个之后对我最初答案的更新。是的,可以将CvVideoCamera 与用 Swift 编写的视图控制器一起使用。如果你只是想用它在你的应用中显示来自摄像头的视频,那真的很简单。
#import <opencv2/highgui/cap_ios.h> 通过桥接头。然后,在您的视图控制器中:
class ViewController: UIViewController, CvVideoCameraDelegate {
...
var myCamera : CvVideoCamera!
override func viewDidLoad() {
...
myCamera = CvVideoCamera(parentView: imageView)
myCamera.delegate = self
...
}
}
ViewController 实际上不能符合CvVideoCameraDelegate 协议,但CvVideoCamera 在没有委托的情况下将无法工作,因此我们通过声明ViewController 来解决此问题以采用该协议而不实现其任何方法.这将触发编译器警告,但来自摄像头的视频流将显示在图像视图中。
当然,您可能希望实现CvVideoCameraDelegate 的(仅)processImage() 方法来在显示视频帧之前对其进行处理。你不能在 Swift 中实现它的原因是它使用了一个 C++ 类型,Mat。
因此,您需要编写一个Objective-C++ 类,其实例可以设置为相机的委托。该Objective-C++ 类中的processImage() 方法将由CvVideoCamera 调用,并依次调用您的Swift 类中的代码。以下是一些示例代码 sn-ps。
在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
在包装器实现中,OpenCVWrapper.mm(它是一个 Objective-C++ 类,因此扩展名为 .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
然后你将#import "OpenCVWrapper.h" 放在桥接头中,Swift 视图控制器可能如下所示:
class ViewController: UIViewController {
...
var videoCameraWrapper : CvVideoCameraWrapper!
override func viewDidLoad() {
...
self.videoCameraWrapper = CvVideoCameraWrapper(controller:self, andImageView:imageView)
...
}
请参阅https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html,了解前向声明和 Swift/C++/Objective-C 互操作。网上有很多关于 #ifdef __cplusplus 和 extern "C" 的信息(如果你需要的话)。
在processImage() 委托方法中,您可能需要与一些 OpenCV API 进行交互,您还必须为此编写包装器。您可以在其他地方找到一些相关信息,例如:Using OpenCV in Swift iOS
2019 年 9 月 3 日更新
应社区要求,见 cmets,示例代码已放在 GitHub 上https://github.com/aperedera/opencv-swift-examples。
此外,在撰写本文时,OpenCV iOS 框架的当前版本不再允许 Swift 代码使用声明 CvVideoCameraDelegate 协议的标头(现在位于 videoio/cap_ios.h),因此您不能只将其包含在桥接头中,并声明视图控制器符合协议,以便在您的应用中简单地显示摄像头视频。