在我有机会亲自尝试后,这是对我的初始答案的更新。 是的,可以在使用Swift编写的视图控制器中使用CvVideoCamera
。 如果您只想在应用程序中显示来自相机的视频,则非常容易。
通过桥接头文件导入#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 类中的代码。以下是一些示例代码片段。
在
OpenCVWrapper.h
中:
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif
@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;
@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];
...
videoCamera.delegate = self;
return self;
}
#ifdef __cplusplus
- (void)processImage:(Mat&)image
{
...
}
#endif
...
@end
然后在桥接头文件中添加#import "OpenCVWrapper.h"
,Swift的视图控制器可能看起来像这样:
class ViewController: UIViewController {
...
var videoCameraWrapper : CvVideoCameraWrapper!
override func viewDidLoad() {
...
self.videoCameraWrapper = CvVideoCameraWrapper(controller:self, andImageView:imageView)
...
}
请参阅有关前置声明和Swift/C++/Objective-C互操作性的内容:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html。如果需要,网络上有大量关于
#ifdef __cplusplus
和
extern "C"
的信息。
在
processImage()
委托方法中,您可能需要与一些OpenCV API交互,因此您还需要编写包装器。您可以在其他地方找到一些信息,例如这里:
Using OpenCV in Swift iOS
更新于09/03/2019
应社区要求(请参见评论),示例代码已放置在GitHub上:
https://github.com/aperedera/opencv-swift-examples。
此外,截至本文撰写时,当前版本的OpenCV iOS框架不再允许Swift代码使用头文件(现在在videoio/cap_ios.h中),该头文件声明了
CvVideoCameraDelegate
协议,因此您不能只将其包含在桥接头文件中并声明视图控制器符合协议以简单地在应用程序中显示相机视频。