Core ML框架詳細(xì)解析(二十) —— 在iOS設(shè)備上使用Style Transfer創(chuàng)建一個(gè)自定義圖像濾波器(一)

版本記錄

版本號(hào) 時(shí)間
V1.0 2022.09.11 星期日

前言

目前世界上科技界的所有大佬一致認(rèn)為人工智能是下一代科技革命,蘋果作為科技界的巨頭,當(dāng)然也會(huì)緊跟新的科技革命的步伐,其中ios API 就新出了一個(gè)框架Core ML。ML是Machine Learning的縮寫,也就是機(jī)器學(xué)習(xí),這正是現(xiàn)在很火的一個(gè)技術(shù),它也是人工智能最核心的內(nèi)容。感興趣的可以看我寫的下面幾篇。
1. Core ML框架詳細(xì)解析(一) —— Core ML基本概覽
2. Core ML框架詳細(xì)解析(二) —— 獲取模型并集成到APP中
3. Core ML框架詳細(xì)解析(三) —— 利用Vision和Core ML對(duì)圖像進(jìn)行分類
4. Core ML框架詳細(xì)解析(四) —— 將訓(xùn)練模型轉(zhuǎn)化為Core ML
5. Core ML框架詳細(xì)解析(五) —— 一個(gè)Core ML簡單示例(一)
6. Core ML框架詳細(xì)解析(六) —— 一個(gè)Core ML簡單示例(二)
7. Core ML框架詳細(xì)解析(七) —— 減少Core ML應(yīng)用程序的大?。ㄒ唬?/a>
8. Core ML框架詳細(xì)解析(八) —— 在用戶設(shè)備上下載和編譯模型(一)
9. Core ML框架詳細(xì)解析(九) —— 用一系列輸入進(jìn)行預(yù)測(一)
10. Core ML框架詳細(xì)解析(十) —— 集成自定義圖層(一)
11. Core ML框架詳細(xì)解析(十一) —— 創(chuàng)建自定義圖層(一)
12. Core ML框架詳細(xì)解析(十二) —— 用scikit-learn開始機(jī)器學(xué)習(xí)(一)
13. Core ML框架詳細(xì)解析(十三) —— 使用Keras和Core ML開始機(jī)器學(xué)習(xí)(一)
14. Core ML框架詳細(xì)解析(十四) —— 使用Keras和Core ML開始機(jī)器學(xué)習(xí)(二)
15. Core ML框架詳細(xì)解析(十五) —— 機(jī)器學(xué)習(xí):分類(一)
16. Core ML框架詳細(xì)解析(十六) —— 人工智能和IBM Watson Services(一)
17. Core ML框架詳細(xì)解析(十七) —— Core ML 和 Vision簡單示例(一)
18. Core ML框架詳細(xì)解析(十八) —— 基于Core ML 和 Vision的設(shè)備上的訓(xùn)練(一)
19. Core ML框架詳細(xì)解析(十九) —— 基于Core ML 和 Vision的設(shè)備上的訓(xùn)練(二)

開始

首先看下主要內(nèi)容:

Style Transfer(風(fēng)格遷移)是一種機(jī)器學(xué)習(xí)技術(shù)。 通過這個(gè),您可以將任何給定的圖像風(fēng)格化為另一個(gè)! 在本教程中,您將學(xué)習(xí)如何利用 AppleML 框架在您的 iOS 設(shè)備上實(shí)現(xiàn)這一目標(biāo)。內(nèi)容來自翻譯

接著看下寫作環(huán)境

Swift 5.5, iOS 15, Xcode 13

下面就是正文了

多年來,Apple 的機(jī)器學(xué)習(xí)框架變得越來越強(qiáng)大。Style TransferNeural Style Transfer,均是框架提供的一種技術(shù)。通過style transfer,您可以將一張圖片變成一張新圖片,并將其風(fēng)格化為第三張圖片。在本教程中,您將學(xué)習(xí)如何利用 Apple 的 ML 框架直接在您的 iOS 設(shè)備上實(shí)現(xiàn)這一目標(biāo)!

iOSmacOS 中的機(jī)器學(xué)習(xí) (ML) 依賴于兩個(gè)核心 Apple 框架 - CreateMLCoreML。 CreateML 允許您構(gòu)建和訓(xùn)練 ML 模型,CoreML 允許您運(yùn)行這些模型。

CreateML 最初僅可用于 macOS 以生成模型。然后,您可以捆綁這些模型以在 macOS、iOSiPadOS 應(yīng)用程序中使用。

2021 年,Apple 將該框架提供給 iOS 15iPadOS 15?,F(xiàn)在,CreateML 框架允許在設(shè)備上訓(xùn)練和創(chuàng)建模型。

在本教程中,您將學(xué)習(xí):

  • 如何在設(shè)備上創(chuàng)建 ML 模型。
  • 如何使用模型生成stylized圖像。
  • 機(jī)器學(xué)習(xí)訓(xùn)練和預(yù)測的核心概念。

注意:iOS 模擬器不支持本教程中使用的 API。 您需要 iOS 設(shè)備和此應(yīng)用的開發(fā)者帳戶。 選擇模擬器作為deployment target會(huì)使 Xcode無法編譯!

打開啟動(dòng)項(xiàng)目,啟動(dòng)項(xiàng)目是一個(gè)名為 Petra 的簡單應(yīng)用程序。

在 Xcode 中打開啟動(dòng)項(xiàng)目,然后在您的設(shè)備上構(gòu)建并運(yùn)行它。 讓自己熟悉應(yīng)用程序的 UI 和代碼庫。

這個(gè)應(yīng)用程序有一個(gè)單一的屏幕,允許您選擇兩個(gè)圖像。 第一個(gè)圖像是一個(gè)style image,它指示需要什么樣式。 第二個(gè)圖像,即user-selected image,將應(yīng)用所需的樣式。

底部的Apply Style按鈕! 應(yīng)該將user image轉(zhuǎn)換為selected style。 在本教程結(jié)束時(shí)放入缺失的部分后,此按鈕將起作用。

對(duì)于這個(gè)應(yīng)用程序,您將創(chuàng)建一個(gè) MLModel,用于對(duì)您的寵物照片進(jìn)行樣式化。

在本教程中,您將訓(xùn)練模型將樣式應(yīng)用于寵物,例如貓或狗,或者大象或雞。 您可以應(yīng)用相同的原則來創(chuàng)建專為您的寵物訓(xùn)練的模型。


What is Style Transfer?

Style transfer是一種將一幅圖像的內(nèi)容與另一幅圖像的風(fēng)格相融合的技術(shù)。 ML 模型從樣式輸入中學(xué)習(xí)樣式,包括圖案、顏色或紋理。 然后它使用它以該樣式重新組合內(nèi)容輸入。

該模型從樣式內(nèi)容創(chuàng)建構(gòu)建塊。 然后它會(huì)使用這些塊重新創(chuàng)建您的內(nèi)容,就像您在 Minecraft 游戲中所做的那樣。

在上面的示例中,平鋪/圖案圖像 A 充當(dāng)提取樣式(例如顏色、圖案、紋理)的源。 將樣式應(yīng)用于圖像 B 以生成風(fēng)格化的輸出圖像 C。

聽起來像魔術(shù),不是嗎?

這種技術(shù)有各種各樣的應(yīng)用,從數(shù)字藝術(shù)到虛擬現(xiàn)實(shí)。 正如在 Google Stadia 平臺(tái)上演示的那樣,它還在游戲中找到了自己的位置。 Apple 的 ARKit 還支持style transfer以對(duì)特定場景進(jìn)行風(fēng)格化。


Preparing the Dataset

要?jiǎng)?chuàng)建模型,您必須使用機(jī)器學(xué)習(xí)算法處理訓(xùn)練集。 iOS 中的 CreateML 框架也不例外,它提供了訓(xùn)練模型所需的所有功能。

訓(xùn)練數(shù)據(jù)應(yīng)盡可能接近預(yù)期的用戶內(nèi)容。例如,對(duì)于一個(gè)風(fēng)格化人臉的應(yīng)用程序,您需要人像來訓(xùn)練模型。

對(duì)于本教程,您將需要寵物圖像來訓(xùn)練模型。 您將使用來自 Kaggle 的一小部分?jǐn)?shù)據(jù),其中包含貓和狗的圖片。 不要擔(dān)心下載整個(gè)數(shù)據(jù)集。 示例項(xiàng)目已經(jīng)有我們的小型數(shù)據(jù)集,您將在本教程中使用它。

Finder 中打開項(xiàng)目目錄,找到 TrainingData 文件夾。

出于演示目的,該項(xiàng)目包含一個(gè)示例風(fēng)格化圖像。 您可以在項(xiàng)目中的 Assets.xcassets 下看到 PresetStyle_1 圖片。

回顧一下,這就是您在啟動(dòng)項(xiàng)目中所擁有的:

  • 1) Training Data - 訓(xùn)練數(shù)據(jù):包含寵物圖像的目錄作為我們的訓(xùn)練集。
  • 2) Sample Style Image - 樣本風(fēng)格圖像:具有獨(dú)特紋理、顏色或圖案的樣本藝術(shù)或平鋪圖像。

注意:您也可以包含自己的一組寵物圖像以提高模型的準(zhǔn)確性。

接下來,您將使用數(shù)據(jù)創(chuàng)建和訓(xùn)練模型。


Training the Model

與任何機(jī)器學(xué)習(xí)一樣,模型訓(xùn)練是風(fēng)格遷移(style transfer)的主要步驟。 讓訓(xùn)練開始吧!

打開 MLModelHandling 組中的 MLModelTrainer.swift。 替換內(nèi)容
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) 您創(chuàng)建數(shù)據(jù)源,它是一個(gè) MLStyleTransfer.DataSource。這告訴模型要從哪里訓(xùn)練數(shù)據(jù)。
  • 2) 您可以通過 MLTrainingSessionParameters 為訓(xùn)練階段指定參數(shù):
    a) sessionDirectory:保存會(huì)話期間生成的數(shù)據(jù)。
    b) reportInterval:會(huì)話報(bào)告進(jìn)度的迭代次數(shù)。
    c) checkpointInterval:會(huì)話保存檢查點(diǎn)之后的迭代次數(shù)。
    d) iterations:為會(huì)話運(yùn)行的迭代總數(shù)。
  • 3) 您還設(shè)置了 ModelParameters
    a) algorithm:風(fēng)格遷移任務(wù)的訓(xùn)練算法,優(yōu)先考慮速度(.cnnLite)或質(zhì)量(.cnn)。
    b) validation:在訓(xùn)練期間用于驗(yàn)證的圖像 - 來自訓(xùn)練集中的一張。
    c) maxIterations:樣式遷移模型可以使用的最大訓(xùn)練迭代次數(shù)。當(dāng)您在 sessionParams 中設(shè)置迭代時(shí),這將被忽略。
    d) textelDensity:定義樣式細(xì)節(jié)的粗細(xì)程度。
    e) styleStrength:指定樣式對(duì)內(nèi)容圖像的影響程度。

您將在以下部分中查看其中一些參數(shù)的效果。

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

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

MLStyleTransfer.train(trainingData:parameters:sessionParameters:) 是一種可以做到這一切的方法! 您將上面創(chuàng)建的參數(shù)和數(shù)據(jù)源傳遞給它。 它返回一個(gè)用于處理訓(xùn)練結(jié)果的 MLJob 對(duì)象。

調(diào)用此方法會(huì)啟動(dòng)異步風(fēng)格遷移模型訓(xùn)練會(huì)話。`

接下來,您將學(xué)習(xí)如何使用訓(xùn)練的輸出。


On-Device Model Generation

訓(xùn)練完成后,模型就可以使用了。 現(xiàn)在你沒有對(duì)創(chuàng)建的模型做任何事情。 所以讓我們現(xiàn)在解決這個(gè)問題。

打開 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)

在這里,一旦訓(xùn)練完成,您將使用 Combine 來獲得結(jié)果。 在 receiveValue 閉包中,您將獲得經(jīng)過訓(xùn)練的模型,我們將其存儲(chǔ)在文件系統(tǒng)中以備后用。

構(gòu)建并運(yùn)行。

當(dāng)您運(yùn)行該應(yīng)用程序時(shí),為您的可愛寵物選擇一張風(fēng)格的圖片和一張圖片(如果您沒有寵物,請?jiān)诨ヂ?lián)網(wǎng)上查找圖片?。?然后您可以選擇Apply Style! 看看會(huì)發(fā)生什么。

注意:培訓(xùn)可能需要一段時(shí)間才能完成。 觀察 Xcode 控制臺(tái)的進(jìn)度。

即使它已經(jīng)完成,您也不會(huì)看到寵物的程式化圖像。 但是,模型生成已完成。 `Xcode 控制臺(tái)顯示類似于以下內(nèi)容的信息:

注意:查看參考部分的鏈接以了解有關(guān)各種損失方程的更多信息。 您會(huì)注意到的一件事是,隨著迭代次數(shù)的增加,總損失會(huì)不斷減少。 總損失是內(nèi)容損失和風(fēng)格損失的總和。 因此,總損失越少,模型的效率就越高。

這些設(shè)備生成重要數(shù)據(jù)。 要查看它們,請從 Xcode 菜單中選擇 Window ? Devices and Simulators。 現(xiàn)在,在 Devices 下選擇您的設(shè)備,然后在 Installed Apps 下選擇 Petra。 選擇 Actions 按鈕并選擇 Download Container,如下面的屏幕截圖所示。

將文件保存到您的 Mac。 這可能需要一段時(shí)間才能下載,因此請確保等到下載完成。 使用 Finder,導(dǎo)航到下載的文件,右鍵單擊 — Show Package Contents以查看內(nèi)部。 內(nèi)容如下所示:

導(dǎo)航到 AppData ? Documents ? Session。 每個(gè)會(huì)話將有一個(gè)文件夾,即每次點(diǎn)擊Apply Style按鈕時(shí)。

在每個(gè)會(huì)話的文件夾中,您將看到訓(xùn)練數(shù)據(jù)、各種元數(shù)據(jù),最重要的是,生成的 CoreML 模型保存在文件名 StyleTransfer.mlmodel 下。


Learning From User’s Data

當(dāng)您使用用戶數(shù)據(jù)時(shí),設(shè)備上學(xué)習(xí)的定制變得無限。 因?yàn)殪`感隨時(shí)隨地都會(huì)來襲,用戶可以簡單地拍照并用于造型。 在這種情況下,個(gè)性化并不意味著失去您的隱私,因?yàn)閿?shù)據(jù)永遠(yuǎn)不必通過設(shè)備上的學(xué)習(xí)離開設(shè)備。

從用戶數(shù)據(jù)中學(xué)習(xí)可以改善結(jié)果。 然而,訓(xùn)練集應(yīng)該盡可能接近預(yù)期的輸入圖像。 如果用戶有一只寵物貓,那么包含貓圖像的訓(xùn)練集會(huì)產(chǎn)生更好的結(jié)果。

同樣,由于照明和背景的差異,使用室內(nèi)圖像訓(xùn)練的模型在室外測試圖像上可能表現(xiàn)不佳,如下所示。

好的培訓(xùn)會(huì)帶來好的學(xué)習(xí)。 但在某些情況下,過多的迭代和過多的訓(xùn)練數(shù)據(jù)可能會(huì)導(dǎo)致過擬合。 這意味著該模型正在學(xué)習(xí)不適用于大多數(shù)情況的細(xì)微差別。 在這種情況下,減少訓(xùn)練迭代會(huì)有所幫助。

打開 Constants.swift 文件并檢查以下內(nèi)容:

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

模型訓(xùn)練使用此處定義的值。 您將很快看到這些值如何影響style transfer輸出。

現(xiàn)在,轉(zhuǎn)到 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。 根據(jù) Apple 的文檔:

  • cnn:一種風(fēng)格轉(zhuǎn)移(style-transfer)訓(xùn)練算法,可生成優(yōu)先考慮圖像質(zhì)量而非速度的模型。
  • cnnLite:一種風(fēng)格轉(zhuǎn)移(style-transfer)訓(xùn)練算法,可生成將速度置于圖像質(zhì)量之上的模型。

使用這些參數(shù),您將能夠微調(diào)您的模型以獲得更好的個(gè)性化。

在下一節(jié)課中,您將充分利用模型和訓(xùn)練并實(shí)際設(shè)置圖像樣式。 準(zhǔn)備好?


Style On!

現(xiàn)在您已經(jīng)有了一個(gè)完美的模型,可以使用它來生成您獨(dú)特的寵物藝術(shù)。

打開 MLPredictor.swift 并將 predictUsingModel(_: inputImage: onCompletion:) 方法的內(nèi)容替換為以下代碼。

// 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)
}

這里發(fā)生了一些事情:

  • 1) 在您可以使用模型進(jìn)行預(yù)測之前,首先編譯模型。 然后將其初始化為 MLModel 對(duì)象。 編譯后的文件作為 ModelName.mlmodelc 保存在一個(gè)臨時(shí)目錄中。

注意:與編譯后的 mlmodelc 文件相比,mlmodel 文件占用的空間更少。 這是一種節(jié)省應(yīng)用程序空間或從服務(wù)器下載模型的技術(shù)。

  • 2) 在這里,您創(chuàng)建模型所需的 MLDictionaryFeatureProvider 字典以進(jìn)行預(yù)測。 您還使用模型的約束和選項(xiàng)格式化輸入圖像。 您生成一個(gè) MLFeatureValue 并傳遞給 MLDictionaryFeatureProvider 的構(gòu)造函數(shù)。

要最終生成風(fēng)格化圖像,請?jiān)谄浜筇砑右韵麓a。

// 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) 調(diào)用 prediction(from:) 方法執(zhí)行單個(gè)預(yù)測并輸出 MLFeatureProvider。 然后從中提取生成的圖像并從圖像緩沖區(qū)創(chuàng)建一個(gè) UIImage 實(shí)例。

瞧! stylizedUIImage 是將樣式混合到您的寵物圖像中的輸出圖像。

構(gòu)建并運(yùn)行。

點(diǎn)擊Apply Style! 選擇寵物形象和風(fēng)格后。 與以前一樣,該處理需要幾分鐘才能完成。 之后,您現(xiàn)在應(yīng)該在屏幕上看到結(jié)果:

只用幾行代碼就可以訓(xùn)練和生成風(fēng)格化的圖像,這不是很神奇嗎?

注意:風(fēng)格化的圖像可能看起來被裁剪。這是因?yàn)樗夏P徒邮艿某叽纭D谇懊娴?imageOptions 中將 .cropAndScale 的值設(shè)置為 .centerCrop

等待!那不是全部!如果結(jié)果達(dá)不到您的想象,您可以對(duì)其進(jìn)行微調(diào)。

您現(xiàn)在將看到調(diào)整訓(xùn)練模型的參數(shù)如何影響結(jié)果。前往 Constants.swift 并找到 MLModelParam 枚舉。在接下來的部分中,您將了解每一個(gè)的含義。隨意玩數(shù)字并隨時(shí)重新運(yùn)行應(yīng)用程序。

1. Style Density

Style density也稱為Textel Density。這控制了模型應(yīng)該學(xué)習(xí)風(fēng)格的粗略或精細(xì)程度。當(dāng)您使用更高/更低的值時(shí),這會(huì)產(chǎn)生明顯的風(fēng)格化結(jié)果。

樣式密度當(dāng)前設(shè)置為 128,小于默認(rèn)值 256。請注意,這應(yīng)始終為 4 的倍數(shù),推薦范圍為 641024。

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

2. Style Strength

較高的值會(huì)使模型學(xué)習(xí)更多的風(fēng)格和更少的內(nèi)容。 較小的值學(xué)會(huì)做更少的樣式。

在示例中,它設(shè)置為 5,這是默認(rèn)值。 它的范圍可以從 110。

以下是它如何影響您的結(jié)果的示例:

請注意,當(dāng)您設(shè)置iterations會(huì)話參數(shù)時(shí),模型參數(shù)中的 maxIterations 值將被忽略。

玩轉(zhuǎn)迭代、style density and style strength,為您的寵物打造一個(gè)討人喜歡的模型。

如果圖像的style transfer很酷,請考慮擴(kuò)展此應(yīng)用以在視頻上應(yīng)用樣式。

如果您有興趣了解有關(guān)style transfer或 Apple ML 框架的更多信息,請查看:

本教程和示例項(xiàng)目中用于圖像的來源:

參考文章

后記

本篇主要講述了在iOS設(shè)備上使用Style Transfer創(chuàng)建一個(gè)自定義圖像濾波器,感興趣的給個(gè)贊或者關(guān)注~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容