Core ML框架详细解析(二十) —— 在iOS设备上使用Style Transfer创建一个自定义图像滤波器(一)

版本记录

版本号 时间
V1.0 2022.09.11 星期日

前言

目前世界上科技界的所有大佬一致认为人工智能是下一代科技革命,苹果作为科技界的巨头,当然也会紧跟新的科技革命的步伐,其中ios API 就新出了一个框架Core ML。ML是Machine Learning的缩写,也就是机器学习,这正是现在很火的一个技术,它也是人工智能最核心的内容。感兴趣的可以看我写的下面几篇。
1. Core ML框架详细解析(一) —— Core ML基本概览
2. Core ML框架详细解析(二) —— 获取模型并集成到APP中
3. Core ML框架详细解析(三) —— 利用Vision和Core ML对图像进行分类
4. Core ML框架详细解析(四) —— 将训练模型转化为Core ML
5. Core ML框架详细解析(五) —— 一个Core ML简单示例(一)
6. Core ML框架详细解析(六) —— 一个Core ML简单示例(二)
7. Core ML框架详细解析(七) —— 减少Core ML应用程序的大小(一)
8. Core ML框架详细解析(八) —— 在用户设备上下载和编译模型(一)
9. Core ML框架详细解析(九) —— 用一系列输入进行预测(一)
10. Core ML框架详细解析(十) —— 集成自定义图层(一)
11. Core ML框架详细解析(十一) —— 创建自定义图层(一)
12. Core ML框架详细解析(十二) —— 用scikit-learn开始机器学习(一)
13. Core ML框架详细解析(十三) —— 使用Keras和Core ML开始机器学习(一)
14. Core ML框架详细解析(十四) —— 使用Keras和Core ML开始机器学习(二)
15. Core ML框架详细解析(十五) —— 机器学习:分类(一)
16. Core ML框架详细解析(十六) —— 人工智能和IBM Watson Services(一)
17. Core ML框架详细解析(十七) —— Core ML 和 Vision简单示例(一)
18. Core ML框架详细解析(十八) —— 基于Core ML 和 Vision的设备上的训练(一)
19. Core ML框架详细解析(十九) —— 基于Core ML 和 Vision的设备上的训练(二)

开始

首先看下主要内容:

Style Transfer(风格迁移)是一种机器学习技术。 通过这个,您可以将任何给定的图像风格化为另一个! 在本教程中,您将学习如何利用 AppleML 框架在您的 iOS 设备上实现这一目标。内容来自翻译

接着看下写作环境

Swift 5.5, iOS 15, Xcode 13

下面就是正文了

多年来,Apple 的机器学习框架变得越来越强大。Style TransferNeural Style Transfer,均是框架提供的一种技术。通过style transfer,您可以将一张图片变成一张新图片,并将其风格化为第三张图片。在本教程中,您将学习如何利用 Apple 的 ML 框架直接在您的 iOS 设备上实现这一目标!

iOSmacOS 中的机器学习 (ML) 依赖于两个核心 Apple 框架 - CreateMLCoreMLCreateML 允许您构建和训练 ML 模型,CoreML 允许您运行这些模型。

CreateML 最初仅可用于 macOS 以生成模型。然后,您可以捆绑这些模型以在 macOSiOSiPadOS 应用程序中使用。

2021 年,Apple 将该框架提供给 iOS 15iPadOS 15。现在,CreateML 框架允许在设备上训练和创建模型。

在本教程中,您将学习:

  • 如何在设备上创建 ML 模型。
  • 如何使用模型生成stylized图像。
  • 机器学习训练和预测的核心概念。

注意:iOS 模拟器不支持本教程中使用的 API。 您需要 iOS 设备和此应用的开发者帐户。 选择模拟器作为deployment target会使 Xcode无法编译!

打开启动项目,启动项目是一个名为 Petra 的简单应用程序。

在 Xcode 中打开启动项目,然后在您的设备上构建并运行它。 让自己熟悉应用程序的 UI 和代码库。

这个应用程序有一个单一的屏幕,允许您选择两个图像。 第一个图像是一个style image,它指示需要什么样式。 第二个图像,即user-selected image,将应用所需的样式。

底部的Apply Style按钮! 应该将user image转换为selected style。 在本教程结束时放入缺失的部分后,此按钮将起作用。

对于这个应用程序,您将创建一个 MLModel,用于对您的宠物照片进行样式化。

在本教程中,您将训练模型将样式应用于宠物,例如猫或狗,或者大象或鸡。 您可以应用相同的原则来创建专为您的宠物训练的模型。


What is Style Transfer?

Style transfer是一种将一幅图像的内容与另一幅图像的风格相融合的技术。 ML 模型从样式输入中学习样式,包括图案、颜色或纹理。 然后它使用它以该样式重新组合内容输入。

该模型从样式内容创建构建块。 然后它会使用这些块重新创建您的内容,就像您在 Minecraft 游戏中所做的那样。

在上面的示例中,平铺/图案图像 A 充当提取样式(例如颜色、图案、纹理)的源。 将样式应用于图像 B 以生成风格化的输出图像 C

听起来像魔术,不是吗?

这种技术有各种各样的应用,从数字艺术到虚拟现实。 正如在 Google Stadia 平台上演示的那样,它还在游戏中找到了自己的位置。 Apple 的 ARKit 还支持style transfer以对特定场景进行风格化。


Preparing the Dataset

要创建模型,您必须使用机器学习算法处理训练集。 iOS 中的 CreateML 框架也不例外,它提供了训练模型所需的所有功能。

训练数据应尽可能接近预期的用户内容。例如,对于一个风格化人脸的应用程序,您需要人像来训练模型。

对于本教程,您将需要宠物图像来训练模型。 您将使用来自 Kaggle 的一小部分数据,其中包含猫和狗的图片。 不要担心下载整个数据集。 示例项目已经有我们的小型数据集,您将在本教程中使用它。

Finder 中打开项目目录,找到 TrainingData 文件夹。

出于演示目的,该项目包含一个示例风格化图像。 您可以在项目中的 Assets.xcassets 下看到 PresetStyle_1 图片。

回顾一下,这就是您在启动项目中所拥有的:

  • 1) Training Data - 训练数据:包含宠物图像的目录作为我们的训练集。
  • 2) Sample Style Image - 样本风格图像:具有独特纹理、颜色或图案的样本艺术或平铺图像。

注意:您也可以包含自己的一组宠物图像以提高模型的准确性。

接下来,您将使用数据创建和训练模型。


Training the Model

与任何机器学习一样,模型训练是风格迁移(style transfer)的主要步骤。 让训练开始吧!

打开 MLModelHandling 组中的 MLModelTrainer.swift。 替换内容
trainModel(using:validationImage:sessionDir:onCompletion:)方法,代码如下。

// 1
let dataSource = MLStyleTransfer.DataSource.images(
    styleImage: styleImage,
    contentDirectory: Constants.Path.trainingImagesDir ?? Bundle.main.bundleURL,
    processingOption: nil)
// 2
let sessionParams = MLTrainingSessionParameters(
    sessionDirectory: sessionDir,
    reportInterval: Constants.MLSession.reportInterval,
    checkpointInterval: Constants.MLSession.checkpointInterval,
    iterations: Constants.MLSession.iterations)
// 3
let modelParams = MLStyleTransfer.ModelParameters(
    algorithm: .cnn,
    validation: .content(validationImage),
    maxIterations: Constants.MLModelParam.maxIterations,
    textelDensity: Constants.MLModelParam.styleDensity,
    styleStrength: Constants.MLModelParam.styleStrength)

以下是代码的情况:

  • 1) 您创建数据源,它是一个 MLStyleTransfer.DataSource。这告诉模型要从哪里训练数据。
  • 2) 您可以通过 MLTrainingSessionParameters 为训练阶段指定参数:
    a) sessionDirectory:保存会话期间生成的数据。
    b) reportInterval:会话报告进度的迭代次数。
    c) checkpointInterval:会话保存检查点之后的迭代次数。
    d) iterations:为会话运行的迭代总数。
  • 3) 您还设置了 ModelParameters
    a) algorithm:风格迁移任务的训练算法,优先考虑速度(.cnnLite)或质量(.cnn)。
    b) validation:在训练期间用于验证的图像 - 来自训练集中的一张。
    c) maxIterations:样式迁移模型可以使用的最大训练迭代次数。当您在 sessionParams 中设置迭代时,这将被忽略。
    d) textelDensity:定义样式细节的粗细程度。
    e) styleStrength:指定样式对内容图像的影响程度。

您将在以下部分中查看其中一些参数的效果。

最后,在同一方法中的modelParams之后添加以下代码:

// 4
guard let job = try? MLStyleTransfer.train(
    trainingData: dataSource,
    parameters: modelParams,
    sessionParameters: sessionParams) else {
    onCompletion(nil)
    return
}

MLStyleTransfer.train(trainingData:parameters:sessionParameters:) 是一种可以做到这一切的方法! 您将上面创建的参数和数据源传递给它。 它返回一个用于处理训练结果的 MLJob 对象。

调用此方法会启动异步风格迁移模型训练会话。`

接下来,您将学习如何使用训练的输出。


On-Device Model Generation

训练完成后,模型就可以使用了。 现在你没有对创建的模型做任何事情。 所以让我们现在解决这个问题。

打开 MLModelTrainer.swift。 然后将下面的代码添加到 trainModel(using:validationImage:sessionDir:onCompletion:)方法的末尾:

// 5
let modelPath = sessionDir.appendingPathComponent(Constants.Path.modelFileName)
job.result.sink(receiveCompletion: { result in
    debugPrint(result)
}, receiveValue: { model in
    do {
        try model.write(to: modelPath)
        onCompletion(modelPath)
        return
    } catch {
        debugPrint("Error saving ML Model: \(error.localizedDescription)")
    }
    onCompletion(nil)
})
.store(in: &subscriptions)

在这里,一旦训练完成,您将使用 Combine 来获得结果。 在 receiveValue 闭包中,您将获得经过训练的模型,我们将其存储在文件系统中以备后用。

构建并运行。

当您运行该应用程序时,为您的可爱宠物选择一张风格的图片和一张图片(如果您没有宠物,请在互联网上查找图片!)。 然后您可以选择Apply Style! 看看会发生什么。

注意:培训可能需要一段时间才能完成。 观察 Xcode 控制台的进度。

即使它已经完成,您也不会看到宠物的程式化图像。 但是,模型生成已完成。 `Xcode 控制台显示类似于以下内容的信息:

注意:查看参考部分的链接以了解有关各种损失方程的更多信息。 您会注意到的一件事是,随着迭代次数的增加,总损失会不断减少。 总损失是内容损失和风格损失的总和。 因此,总损失越少,模型的效率就越高。

这些设备生成重要数据。 要查看它们,请从 Xcode 菜单中选择 Window ▸ Devices and Simulators。 现在,在 Devices 下选择您的设备,然后在 Installed Apps 下选择 Petra。 选择 Actions 按钮并选择 Download Container,如下面的屏幕截图所示。

将文件保存到您的 Mac。 这可能需要一段时间才能下载,因此请确保等到下载完成。 使用 Finder,导航到下载的文件,右键单击 — Show Package Contents以查看内部。 内容如下所示:

导航到 AppData ▸ Documents ▸ Session。 每个会话将有一个文件夹,即每次点击Apply Style按钮时。

在每个会话的文件夹中,您将看到训练数据、各种元数据,最重要的是,生成的 CoreML 模型保存在文件名 StyleTransfer.mlmodel 下。


Learning From User’s Data

当您使用用户数据时,设备上学习的定制变得无限。 因为灵感随时随地都会来袭,用户可以简单地拍照并用于造型。 在这种情况下,个性化并不意味着失去您的隐私,因为数据永远不必通过设备上的学习离开设备。

从用户数据中学习可以改善结果。 然而,训练集应该尽可能接近预期的输入图像。 如果用户有一只宠物猫,那么包含猫图像的训练集会产生更好的结果。

同样,由于照明和背景的差异,使用室内图像训练的模型在室外测试图像上可能表现不佳,如下所示。

好的培训会带来好的学习。 但在某些情况下,过多的迭代和过多的训练数据可能会导致过拟合。 这意味着该模型正在学习不适用于大多数情况的细微差别。 在这种情况下,减少训练迭代会有所帮助。

打开 Constants.swift 文件并检查以下内容:

enum MLModelParam {
  static var maxIterations = 200
  static var styleDensity = 128 // Multiples of 4
  static var styleStrength = 5 // Range 1 to 10
}

模型训练使用此处定义的值。 您将很快看到这些值如何影响style transfer输出。

现在,转到 MLModelTrainer.swift文件并找到下面的代码。

// 3
let modelParams = MLStyleTransfer.ModelParameters(
    algorithm: .cnn,
    validation: .content(validationImage),
    maxIterations: Constants.MLModelParam.maxIterations,
    textelDensity: Constants.MLModelParam.styleDensity,
    styleStrength: Constants.MLModelParam.styleStrength)

正如您之前看到的,您可以使用两种不同的算法之一——.cnn.cnnLite。 根据 Apple 的文档:

  • cnn:一种风格转移(style-transfer)训练算法,可生成优先考虑图像质量而非速度的模型。
  • cnnLite:一种风格转移(style-transfer)训练算法,可生成将速度置于图像质量之上的模型。

使用这些参数,您将能够微调您的模型以获得更好的个性化。

在下一节课中,您将充分利用模型和训练并实际设置图像样式。 准备好?


Style On!

现在您已经有了一个完美的模型,可以使用它来生成您独特的宠物艺术。

打开 MLPredictor.swift 并将 predictUsingModel(_: inputImage: onCompletion:) 方法的内容替换为以下代码。

// 1
guard
    let compiledModel = try? MLModel.compileModel(at: modelPath),
    let mlModel = try? MLModel.init(contentsOf: compiledModel)
else {
    debugPrint("Error reading the ML Model")
    return onCompletion(nil)
}
// 2
let imageOptions: [MLFeatureValue.ImageOption: Any] = [
    .cropAndScale: VNImageCropAndScaleOption.centerCrop.rawValue
]
guard
    let cgImage = inputImage.cgImage,
    let imageConstraint = mlModel.modelDescription.inputDescriptionsByName["image"]?.imageConstraint,
    let inputImg = try? MLFeatureValue(cgImage: cgImage, constraint: imageConstraint, options: imageOptions),
    let inputImage = try? MLDictionaryFeatureProvider(dictionary: ["image": inputImg])
else {
    return onCompletion(nil)
}

这里发生了一些事情:

  • 1) 在您可以使用模型进行预测之前,首先编译模型。 然后将其初始化为 MLModel 对象。 编译后的文件作为 ModelName.mlmodelc 保存在一个临时目录中。

注意:与编译后的 mlmodelc 文件相比,mlmodel 文件占用的空间更少。 这是一种节省应用程序空间或从服务器下载模型的技术。

  • 2) 在这里,您创建模型所需的 MLDictionaryFeatureProvider 字典以进行预测。 您还使用模型的约束和选项格式化输入图像。 您生成一个 MLFeatureValue 并传递给 MLDictionaryFeatureProvider 的构造函数。

要最终生成风格化图像,请在其后添加以下代码。

// 3
guard
  let stylizedImage = try? mlModel.prediction(from: inputImage),
  let imgBuffer = stylizedImage.featureValue(for: "stylizedImage")?.imageBufferValue
else {
  return onCompletion(nil)
}
let stylizedUIImage = UIImage(withCVImageBuffer: imgBuffer)
return onCompletion(stylizedUIImage)

这是该代码的作用:

  • 3) 调用 prediction(from:) 方法执行单个预测并输出 MLFeatureProvider。 然后从中提取生成的图像并从图像缓冲区创建一个 UIImage 实例。

瞧! stylizedUIImage 是将样式混合到您的宠物图像中的输出图像。

构建并运行。

点击Apply Style! 选择宠物形象和风格后。 与以前一样,该处理需要几分钟才能完成。 之后,您现在应该在屏幕上看到结果:

只用几行代码就可以训练和生成风格化的图像,这不是很神奇吗?

注意:风格化的图像可能看起来被裁剪。这是因为它符合模型接受的尺寸。您在前面的 imageOptions 中将 .cropAndScale 的值设置为 .centerCrop

等待!那不是全部!如果结果达不到您的想象,您可以对其进行微调。

您现在将看到调整训练模型的参数如何影响结果。前往 Constants.swift 并找到 MLModelParam 枚举。在接下来的部分中,您将了解每一个的含义。随意玩数字并随时重新运行应用程序。

1. Style Density

Style density也称为Textel Density。这控制了模型应该学习风格的粗略或精细程度。当您使用更高/更低的值时,这会产生明显的风格化结果。

样式密度当前设置为 128,小于默认值 256。请注意,这应始终为 4 的倍数,推荐范围为 641024

在下面的示例中,您可以看到style density如何影响输出。

2. Style Strength

较高的值会使模型学习更多的风格和更少的内容。 较小的值学会做更少的样式。

在示例中,它设置为 5,这是默认值。 它的范围可以从 110

以下是它如何影响您的结果的示例:

请注意,当您设置iterations会话参数时,模型参数中的 maxIterations 值将被忽略。

玩转迭代、style density and style strength,为您的宠物打造一个讨人喜欢的模型。

如果图像的style transfer很酷,请考虑扩展此应用以在视频上应用样式。

如果您有兴趣了解有关style transfer或 Apple ML 框架的更多信息,请查看:

本教程和示例项目中用于图像的来源:

参考文章

后记

本篇主要讲述了在iOS设备上使用Style Transfer创建一个自定义图像滤波器,感兴趣的给个赞或者关注~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容