基于 Core ML 的计算机视觉框架
iOS 11 中集成了 Core ML 框架,即机器学习框架。提供给开发者一系列机器学习的 API,包括 Vison 计算机视觉、NLP 自然语言处理等 API。通过 Core ML 框架,开发者可以将训练好的机器学习模型集成到项应用中,并通过机器学习得到开发者想要的结果。Vision 是建立在 Core ML 基础上的处理计算机视觉相关的 Framework,通过 Vision 开发者可以做高性能的图片分析和用计算机视觉去识别人脸、检测容貌以及对图片和视频中的场景进行分类。
Core ML 介绍
Core ML 是特定框架功能的基础,支持用于用户图像分析的 Vision,用于自然语言处理的 Foundation (如 NSLinguisticTagger 类)和用于评估已经学习到的决策树 GamePlayKit。Core ML 本身构建于低层面的原语上,比如 Accelerate、BNNS、Metal Performance Shaders。
借助 Core ML,您可以将已训练好的机器学习模型,集成到自己的应用当中,Core ML 支持的操作系统:
- iOS 11.0+Beta
- macOS 10.13+Beta
- tvOS 11.0+Beta
- watchOS 4.0+Beta
训练好的模型:
模型的功能是基于新的输入数据进行预测。比如,如果一个模型在一个地区的历史房价数据上进行了训练,那么它就可能能够根据房子的卧室和浴室数量来预测房价。Core ML 支持大量机器学习模型,包括神经网络、树集成、支持向量机和广义的线性模型。
将训练好的模型转换成 Core ML
如果你的模型是使用支持的第三方机器学习工具创建和训练的,那么你可以使用 Core ML Tools 将其转换成 Core ML 模型格式。下表给出了支持的模型和第三方工具。
Core ML Tools 是一个 Python 包(coremltools),托管在 Python Package Index (PyPI) 上。要了解更多有关 Python 包的信息,请参阅:网址。
Vision
Vision 是建立在 Core ML 上层的 Framework。类似 NLP 处理语言,Vision 专门用来处理视觉。Vison 可以进行多种应用场景的机器学习处理,具体如下:
应用场景
- 人脸检测:支持检测笑脸、侧脸、局部遮挡脸部、戴眼镜和帽子等场景,可以标记出人脸的矩形区域
- 人脸特征点:可以标记出人脸和眼睛、眉毛、鼻子、嘴、牙齿的轮廓,以及人脸的中轴线
- 图像配准
- 矩形检测
- 二维码/条形码检测
- 文字检测
- 目标跟踪:脸部,矩形和通用模板
Vision 使用方法
Vision 将各种功能的 Request 提供给一个 RequestHandler,Handler 持有图片信息,并将处理结果分发给每个 Request 的 completion Block 中。可以从 results 属性中得到 Observation 数组,然后进行更新 UI 等操作。因为 completion Block 所执行的队列跟 perform request 的队列相同,所以更新 UI 时记得使用主队列。 Vision 操作流水线分为两类:分析图片和跟踪队列。可以使用图片检测出的物体或矩形结果(Observation)来作为跟踪队列请求(Request)的参数。
开发者可以使用 Vision 来做各种关于图像的 Machine Learning 处理,如人脸检测(Face Detection:Machine Learning 的人脸检测可以检测更多场景下的人脸,比如侧脸,戴眼镜都可以检测出)、人脸标记(Face Landmarks)、图像配准(Image registration)、矩形探测(Rectangle Detection),扫描二维码(Barcode Detection)、文字检测(Text Detection)、物体追踪(Object Tracking)等。更详细的应用请参加已公开文档:[文档] (https://developer.apple.com/documentation/vision)。
Vision 是一个高层次 API,为开发者封装了复杂的机器视觉实现,开发者不需要成为一个机器视觉的专家,只需要明白自己需要什么,就可以使用 Vision 轻易完成。记住两个关键 API:VNImageRequestHandler
、VNSequnenceRequestHandler
。一个处理单张图片,一个处理序列图片如摄像头实时捕捉的场景。使用两个Handler 发起对应的 Request 请求就可以获取到相关结果了,使用起来真的非常方便。如下图:
Vision 中涵盖的重要类
图像识别
- VNImageRequestHandler: 处理单张图片的分析请求的类
- VNSequenceRequestHandler: 处理一系列图片的分析请求的类
人脸检测和识别
- VNDetectFaceRectanglesRequest: 图片中人脸的分析请求类
- VNDetectFaceLandmarksRequest: 图片中人脸特征(眼睛、嘴)的分析请求类
- VNFaceObservation: 通过图片分析请求得到的人脸信息
机器学习图片分析
- VNCoreMLRequest: 使用 Core ML 处理图片生成的请求类
- VNClassificationObservation: 图片分析请求获取的场景分类信息
- VNPixelBufferObservation:Core ML图片分析请求输出的图片信息
- VNCoreMLFeatureValueObservation: Core ML 图片分析请求获取的一系列 key-value 信息
二维码识别
- VNDetectBarcodesRequest: 查找图片中二维码的请求
- VNBarcodeObservation: 图片请求获取的二维码的信息
Image Alignment Analysis(从命名即可知道类的功能)
- VNTranslationalImageRegistrationRequest
- VNHomographicImageRegistrationRequest
- VNImageRegistrationRequest
- VNImageHomographicAlignmentObservation
- VNImageTranslationAlignmentObservation
- VNImageAlignmentObservation
文本检测
- VNDetectHorizonRequest: 图片视角的分析请求
- VNHorizonObservation: 图片视角信息
物体检测和追踪
- VNDetectRectanglesRequest
- VNTrackRectangleRequest
- VNTrackObjectRequest
- VNRectangleObservation
- VNDetectedObjectObservation
Vision 支持的图片数据类型:
- CVPixelBufferRef
- CGImageRef
- CIImage
- NSURL
- NSData
这几乎涵盖了 iOS 中图片相关的 API,很实用很强大。
Vision 有三种 resize 图片的方式,无需使用者再次裁切缩放
- VNImageCropAndScaleOptionCenterCrop
- VNImageCropAndScaleOptionScaleFit
- VNImageCropAndScaleOptionScaleFill
另外性能方面,Vision 与 iOS 上其他几种带人脸检测功能框架的对比情况如下:
使用 Vision 探测人脸的 Demo
typedef void (^RequestBlock)(void);
@interface ViewController ()
@property (nonatomic, strong) UIImageView* imageView;
@property (nonatomic, strong) UILabel* label;
@property (nonatomic, copy) RequestBlock block;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImage* image = [UIImage imageNamed:@"face.png"];
[self createImageView:image];
VNDetectFaceRectanglesRequest* faceRequest = [[VNDetectFaceRectanglesRequest alloc] initWithCompletionHandler:^(VNRequest * _Nonnull request, NSError * _Nullable error)
{
VNDetectFaceRectanglesRequest *faceRequest = (VNDetectFaceRectanglesRequest*)request;
VNFaceObservation*firstObservation = [faceRequest.results firstObject];
CGRect boundingBox = [firstObservation boundingBox];
NSUInteger width =CGImageGetWidth(image.CGImage);
NSUInteger height =CGImageGetHeight(image.CGImage);
CGRect rect =VNImageRectForNormalizedRect(boundingBox,width,height);
CGRect frame = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
self.label.frame = [self.imageView convertRect:frame toView:self.view];
}];
VNImageRequestHandler*handler = [[VNImageRequestHandler alloc] initWithCGImage:image.CGImage options:@{}];
[handler performRequests:@[faceRequest] error:nil];
self.block = ^(void){
[handler performRequests:@[faceRequest] error:nil];
};
}
- (void)createImageView:(UIImage*)image
{
self.imageView = [[UIImageView alloc] initWithImage:image];
self.imageView.frame = CGRectMake(20, 50, CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage));
[self.view addSubview:self.imageView];
self.label = [[UILabel alloc] init];
self.label.backgroundColor = [UIColor clearColor];
self.label.layer.borderWidth = 0.5;
self.label.layer.borderColor = [UIColor redColor].CGColor;
[self.view addSubview:self.label];
}
- (void)moviewImageView
{
CGRect frame = self.imageView.frame;
frame = CGRectMake(frame.origin.x, frame.origin.y+100, frame.size.width, frame.size.height);
[UIView animateWithDuration:3 animations:^{
self.imageView.frame = frame;
}];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch* touch = touches.anyObject;
CGPoint point = [touch locationInView:self.view];
self.imageView.center = point;
self.block();
}
效果如下图所示