CoreML⼊门:构建⼀个简单的图像识别应⽤
译者:智多芯;校对:liberalism,Lision;定稿:CMB
Apple公司在WWDC2017发布了⼏个令开发者感到兴奋的框架和API,⽽在这些新框架中最受欢迎的绝对⾮CoreML
莫属了。开发者可以通过CoreML框架将机器学习模型集成到应⽤程序中,该框架最⼤的优点是使⽤它并不需要开发
者具备额外的神经⽹络或机器学习知识。CoreML框架的另⼀个特点是,只要开发者将已经训练好的数据模型转换成了
CoreML模型即可使⽤。为了演⽰,本⽂将直接使⽤Apple开发者⽹站上提供的⼀个CoreML模型。闲话少说,下⾯
开始学习CoreML。
注:本⽂要求使⽤Xcode9beta编写代码,还需要⼀个安装了iOS11beta的设备(译者注:也可使⽤iOS模拟
器)⽤于测试⽂中实现的功能。虽然Xcode9beta同时⽀持Swift3.2和4.0,但⽂中所有的代码都使⽤了Swift4.0
编写。
什么是CoreML
CoreML使得开发者能够将各种各样的机器学习模型集成到应⽤程序中。它除了⽀持超过30层类型的⼴泛深度学
习,还⽀持如树集成、SVMs和⼴义线性模型等标准模型。CoreML建⽴在像Metal和Accelerate这样的底层技术
之上,因此它能够⽆缝地充分利⽤CPU和GPU以实现性能最⼤化。机器学习模型可直接运⾏在设备上,以⾄于数
据被分析时不需要脱离设备。
-关于CoreML的Apple官⽅⽂档
CoreML是今年在WWDC上随着iOS11发布的⼀个全新的机器学习框架。通过CoreML,开发者可以直接将机器学
习模型集成到应⽤程序中。那么什么是机器学习呢?简单地说,机器学习是赋予计算机学习能⼒的应⽤,⽽不需要明确
地对它编程。⼀个训练好的模型就是结合机器学习算法对⼀些数据集进⾏训练的结果。
作为⼀个应⽤程序开发者,我们主要关⼼的是如何将机器学习模型应⽤到应⽤程序中以实现更有意思的功能。幸运的
是,Apple提供的CoreML框架⼤⼤简化了将不同的机器学习模型集成到应⽤程序中的过程。这为开发者开发如图像识
别、⾃然语⾔处理、⽂本预测等功能提供了⾮常多的可能性。
现在你可能想知道将这种类型的⼈⼯智能加⼊到应⽤程序中会不会很困难,这就是最有意思的部分了,实际上CoreML
⾮常易⽤。在本⽂中,你将会看到只要10⾏代码就可以将CoreML集成到应⽤程序中。
很酷吧?下⾯开始吧!
演⽰程序概览
本⽂将要实现的程序⼗分简单。该程序让⽤户拍摄或者从相册中选择⼀张照⽚,然后机器学习算法将会尝试预测照⽚中
的物体。虽然预测结果可能并不完美,但你将借此了解到如何将CoreML应⽤到应⽤程序上。
开始
⾸先,打开Xcode9beta并创建⼀个新项⽬。为该项⽬选择单视图应⽤程序(SingleViewApp)模板,并确保使⽤的
语⾔设置为Swift。
创建⽤户界⾯
如果你不想从头开始搭建UI界⾯,可以从这⾥下载起始项⽬并直接跳到CoreML部分。
下⾯就开始吧!⾸先打开oard,并添加⼀些UI元素到视图中。选择storyboard中的视图控制器,然后依次
点击Xcode菜单栏:Editor->EmbedIn->NavigationController。随后即可看到⼀个导航栏出现在视图上⽅。将该导航
栏命名为CoreML(或者任何你觉得合适的名字)。
放到视图底端并对其缩放,使其两端刚好与视图两端重合。这样就搭建好了该应⽤的界⾯。
虽然本⽂没涉及到⾃动布局,但还是强烈建议使⽤。如果你没法做到⾃动布局,那就直接在storyboard中选择你将要运
⾏的设备类型。
实现拍照和相册功能
既然已经搭好了界⾯,接着就开始实现功能吧。本节将实现相册和拍照按钮的功能。在中,先遵
从UIImagePickerController所要求的UINavigationControllerDelegate协议。
classViewController:UIViewController,UINavigationControllerDelegate
然后为之前的UILabel和UIImageView新增两个IBOutlet。为了简单起见,本⽂分别将UIImageView和UILabel命名
为imageView和classifier。代码如下所⽰:
importUIKit
classViewController:UIViewController,UINavigationControllerDelegate{
@IBOutletweakvarimageView:UIImageView!
@IBOutletweakvarclassifier:UILabel!
overridefuncviewDidLoad(){
dLoad()
}
overridefuncdidReceiveMemoryWarning(){
eiveMemoryWarning()
}
}
接着还需要实现对应按钮被点击的响应动作,在ViewController中添加如下代码:
@IBActionfunccamera(_nder:Any){
if!ceTypeAvailable(.camera){
return
}
letcameraPicker=UIImagePickerController()
te=lf
Type=.camera
Editing=fal
prent(cameraPicker,animated:true)
}
@IBActionfuncopenLibrary(_nder:Any){
letpicker=UIImagePickerController()
Editing=fal
te=lf
Type=.photoLibrary
prent(picker,animated:true)
}
以上代码创建了⼀个UIImagePickerController类型的常量并确保⽤户⽆法修改已拍摄的照⽚(⽆论该照⽚是刚拍摄的
或者从相册中选择的)。然后将delegate设置为lf,最后将UIImagePickerController展⽰给⽤户。
⾄此还未添加UIImagePickerControllerDelegate对应的⽅法到中,因此Xcode将会有错误提⽰。
这⾥通过extension的形式来实现该协议:
extensionViewController:UIImagePickerControllerDelegate{
funcimagePickerControllerDidCancel(_picker:UIImagePickerController){
dismiss(animated:true,completion:nil)
}
}
上⾯的代码对⽤户取消选择照⽚的动作做了相应处理。到⽬前为⽌代码⼤致如下:
importUIKit
classViewController:UIViewController,UINavigationControllerDelegate{
@IBOutletweakvarimageView:UIImageView!
@IBOutletweakvarclassifier:UILabel!
overridefuncviewDidLoad(){
dLoad()
//Doanyadditionaltupafterloadingtheview,typicallyfromanib.
}
overridefuncdidReceiveMemoryWarning(){
eiveMemoryWarning()
//Dispoofanyresourcesthatcanberecreated.
}
@IBActionfunccamera(_nder:Any){
if!ceTypeAvailable(.camera){
return
}
letcameraPicker=UIImagePickerController()
te=lf
Type=.camera
Editing=fal
prent(cameraPicker,animated:true)
}
@IBActionfuncopenLibrary(_nder:Any){
letpicker=UIImagePickerController()
Editing=fal
te=lf
Type=.photoLibrary
prent(picker,animated:true)
}
}
extensionViewController:UIImagePickerControllerDelegate{
funcimagePickerControllerDidCancel(_picker:UIImagePickerController){
dismiss(animated:true,completion:nil)
}
}
}
确保你有回到storyboard并为所有的IBOutlet和IBAction都建⽴好了连接。
为了访问摄像头和相册,还有做⼀件事。打开并添加两项:Privacy-CameraUsageDeion和Privacy–
PhotoLibraryUsageDeion。这是因为从iOS10开始,访问摄像头和相册需要指明访问原因。
接下来将开始本⽂的核⼼部分了。再声明⼀次,如果你不想从头搭建界⾯,你可以从这⾥下载起始项⽬。
集成CoreML数据模型
现在开始将CoreML数据模型集成到应⽤程序中。正如前⽂所提到的,要使CoreML能正常⼯作还需要提供⼀个训练
好的模型。你可以使⽤⾃⼰训练的模型,但本⽂将使⽤Apple开发者⽹站上提供的已经训练好的模型。
在Apple开发者⽹站的MachineLearning页⾯向下滚动到底部就可以看到4个已经训练好的CoreML模型。
本教程将使⽤Inceptionv3模型,但你也可以尝试下其他三个。在下载了Inceptionv3模型后,将其添加到Xcode项⽬
中,然后看看Xcode都显⽰了哪些信息。
备注:请确保该项⽬的TargetMembersip被选中了,否则应⽤将⽆法访问到该⽂件。
在上⾯的截图中,可以看出该数据模型的类型为神经⽹络分类器。其他需要注意的信息还有模型评估参数,它表⽰该模
型的输⼊和输出参数。本⽂使⽤的模型需要输⼊⼀张299x299的图像,并输出最为可能的类型及其对应每个类型的概
率。
该截图中的另⼀个重要信息是模型类(modelclass),它是机器学习模型(Inceptionv3)⾃动⽣成的可以直接在代码
中使⽤的类。点击Inceptionv3右边的箭头就可以看到该类的源码。
现在将该模型添加到代码中。打开⽂件,在开头导⼊CoreML框架:
importCoreML
接着,为Inceptionv3模型声明⼀个model变量,并在viewWillAppear()⽅法中初始化:
varmodel:Inceptionv3!
overridefuncviewWillAppear(_animated:Bool){
model=Inceptionv3()
}
我知道你现在在想什么。
“为什么不早点对这个模型进⾏初始化?”
“在viewWillAppear⽅法中定义它的意义何在?”
亲爱的朋友,它的意义在于,当应⽤程序尝试识别图像中的物体时,速度会快得多。(译者注:直接在声明model变量
亲爱的朋友,它的意义在于,当应⽤程序尝试识别图像中的物体时,速度会快得多。(译者注:直接在声明model变量
时直接初始化似乎也没什么影响,读者可⾃⾏测试。)
现在回到l,该模型接受的唯⼀输⼊参数是⼀张尺⼨为299x299的图像,所以接下来要处理的就是
如何将⼀张图像转换成这种尺⼨。
转换图⽚
在的extension中,将代码更新成如下代码。它实现了
imagePickerController(_:didFinishPickingMediaWithInfo)⽅法⽤于处理选中的图像:
extensionViewController:UIImagePickerControllerDelegate{
funcimagePickerControllerDidCancel(_picker:UIImagePickerController){
dismiss(animated:true,completion:nil)
}
funcimagePickerController(_picker:UIImagePickerController,didFinishPickingMediaWithInfoinfo:[String:Any]){
s(animated:true)
="AnalyzingImage..."
guardletimage=info["UIImagePickerControllerOriginalImage"]as?UIImageel{
return
}
UIGraphicsBeginImageContextWithOptions(CGSize(width:299,height:299),true,2.0)
(in:CGRect(x:0,y:0,width:299,height:299))
letnewImage=UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
letattrs=[kCVPixelBufferCGImageCompatibilityKey:kCFBooleanTrue,
kCVPixelBufferCGBitmapContextCompatibilityKey:kCFBooleanTrue]asCFDictionary
varpixelBuffer:CVPixelBuffer?
letstatus=CVPixelBufferCreate(kCFAllocatorDefault,Int(),Int(),
kCVPixelFormatType_32ARGB,attrs,&pixelBuffer)
guard(status==kCVReturnSuccess)el{
return
}
CVPixelBufferLockBaAddress(pixelBuffer!,CVPixelBufferLockFlags(rawValue:0))
letpixelData=CVPixelBufferGetBaAddress(pixelBuffer!)
letrgbColorSpace=CGColorSpaceCreateDeviceRGB()
letcontext=CGContext(data:pixelData,width:Int(),height:Int(),
bitsPerComponent:8,bytesPerRow:CVPixelBufferGetBytesPerRow(pixelBuffer!),space:rgbColorSpace,bitmapInfo:
ue)//3
context?.translateBy(x:0,y:)
context?.scaleBy(x:1.0,y:-1.0)
UIGraphicsPushContext(context!)
(in:CGRect(x:0,y:0,width:,height:))
UIGraphicsPopContext()
CVPixelBufferUnlockBaAddress(pixelBuffer!,CVPixelBufferLockFlags(rawValue:0))
=newImage
}
}
imagePickerController(_:didFinishPickingMediaWithInfo)函数中的代码解释如下:
1.#7-11⾏:该⽅法的前⼏⾏将选中的图像从info字典中(使⽤UIImagePickerControllerOriginalImage键)取出。另
外,⼀旦有图像被选中就DismissUIImagePickerController。
2.#13-16⾏:因为本⽂使⽤的模型只接受尺⼨为299x299的图像,因此我们将选中的图像转换为⼀个正⽅形,然后将
其赋值给另⼀个常量newImage。
3.#18-23⾏:将newImage转换为CVPixelBuffer。对于不熟悉CVPixelBuffer的读者来说,它就是⼀个⽤来在内存
中存放像素的图像缓冲区,详情可查阅这⾥。
4.#31-32⾏:将该图像的所有像素转换到独⽴于设备的RGB颜⾊空间。接着创建⼀个容纳所有像素数据的
CGContext,当需要渲染(或者改变)该上下⽂的⼀些基本属性时就可以很轻松的调⽤它。这也是我们这两⾏所做
的事情——对图像进⾏平移和缩放。
5.#34-38⾏:最后,将该图形上下⽂放⼊当前上下⽂中,渲染图像,从栈顶删除该上下⽂,再将
设置成newImage。
如果你现在⽆法理解以上的⼤部分代码也没关系,这只是⼀些超出本⽂范围的CoreImage的⾼级代码⽚段⽽已。你只
需要知道上⾯的代码将选中的图像转换成了数据模型能够接受的形式。我建议你能改动下代码中的数字并留意对应的结
果,以更好地理解上⾯的代码。
使⽤CoreML
现在我们把注意⼒重新放回到CoreML上来。我们使⽤了Inceptionv3模型来实现对象识别。借助CoreML,我们所需
要做的只是添加⼏⾏代码。将以下代码段粘贴到=newImage之后。
guardletprediction=try?tion(image:pixelBuffer!)el{
return
}
="Ithinkthisisa(abel)."
="Ithinkthisisa(abel)."
这就完了!Inceptionv3类⾃动⽣成了⼀个名为prediction(image:)的⽅法,可以⽤来预测给定图像中出现的物体。这⾥
我们将调整后的图像以pixelBuffer作为参数传给了该⽅法。⼀旦String类型的预测结果返回了,就将classifier标签更
新为识别出的物体名称。
是时候测试⼀下这个应⽤了。编译并在模拟器或者你的iPhone(安装了iOS11beta)上运⾏该应⽤,从相册选择或使
⽤摄像头拍摄⼀张照⽚,该应⽤将识别出图像中有什么物体。
在测试该应⽤的过程中,你可能会注意到它并不总能准确地做出预测。其实这并不是代码的问题,问题出在被训练过的
模型上。
总结
希望你已经懂得了如何将CoreML集成到你的应⽤中,本⽂仅仅是⼀篇⼊门教程⽽已。如果你对将训练好的Caffe、
Keras或者SciKit模型转换成CoreML模型感兴趣的话,请继续关注我们的下⼀篇CoreML系列教程。我将教你如何
将⼀个模型转换为CoreML模型。
如果想参考本⽂的演⽰应⽤程序,请查看GitHub上的完整项⽬。
关于CoreML框架的更详细信息,请参考官⽅CoreML⽂档。也可以参考Apple的WWDC2017视频:
•IntroducingCoreML
•CoreMLinDepth
关于CoreML如果你还有什么想说的,记得给我们留⾔哦!
本文发布于:2022-12-29 08:36:07,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/52271.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |