今天的大街上戴口罩的人越來(lái)越多,你可能會(huì)想:他們摘了口罩都長(zhǎng)什么樣呢?至少我們 STRV 機(jī)器學(xué)習(xí)(ML)團(tuán)隊(duì)就有這樣的疑問(wèn)。作為一個(gè)機(jī)器學(xué)習(xí)團(tuán)隊(duì),我們很快意識(shí)到問(wèn)題比想象中更容易解決。
想知道我們是如何設(shè)計(jì)出一種可以從人臉圖像上移除口罩的 ML 工具的嗎?
本文將指導(dǎo)你完成構(gòu)建深度學(xué)習(xí) ML 模型的整個(gè)過(guò)程——從初始設(shè)置、數(shù)據(jù)收集和選擇適當(dāng)?shù)哪P停接?xùn)練和微調(diào)。
在深入研究之前,我們先來(lái)定義任務(wù)的性質(zhì)。我們?cè)噲D解決的問(wèn)題可以看作是 圖像修復(fù),也就是恢復(fù)受損圖像或填充缺失部分的過(guò)程。下面就是圖像修復(fù)的例子:輸入的圖像有一些白色缺失,經(jīng)過(guò)處理這些缺失被補(bǔ)足了。
使用部分卷積進(jìn)行圖像修復(fù)的示例
解決完定義的問(wèn)題后我們?cè)偬嵋稽c(diǎn):除了本文之外,我們還準(zhǔn)備了一個(gè) GitHub 帳戶,其中包含你需要的所有內(nèi)容實(shí)現(xiàn),以及 Jupyter Notebook“mask2face.ipynb”,你可以在其中運(yùn)行本文提到的所有內(nèi)容。只需單擊幾下,即可訓(xùn)練你自己的神經(jīng)網(wǎng)絡(luò)。
接下來(lái),讓我們正式開(kāi)始吧。
一、準(zhǔn)備工作
如果你想在計(jì)算機(jī)上執(zhí)行本文所述的所有步驟,可以克隆此項(xiàng)目。
首先,我們來(lái)為 Python 項(xiàng)目準(zhǔn)備虛擬環(huán)境。你可以使用你喜歡的任何虛擬環(huán)境,只要確保從 environment.yml 和 requirements.txt 安裝所有必需的依賴項(xiàng)即可。如果你熟悉 Conda,還可以在克隆的 GitHub 項(xiàng)目目錄中運(yùn)行以下命令來(lái)初始化 Conda 環(huán)境:
conda env create -f environment.yml conda activate mask2face
現(xiàn)在,你已經(jīng)有了一個(gè)帶有所有必需依賴項(xiàng)的環(huán)境,接下來(lái)我們來(lái)定義目標(biāo)和目的。對(duì)于這個(gè)項(xiàng)目,我們想要?jiǎng)?chuàng)建一個(gè) ML 模型,該模型可以向我們展示戴口罩的人摘下口罩的樣子。我們的模型有一個(gè)輸入——戴口罩的人的圖像;一個(gè)輸出——摘下口罩的人的圖像。
二、實(shí)現(xiàn) 1. 高層 ML 管道
下圖很好地展示了整個(gè)項(xiàng)目的高層管道。
我們從一個(gè)帶有預(yù)先計(jì)算的面部界標(biāo)的面部數(shù)據(jù)集開(kāi)始,該數(shù)據(jù)集是通過(guò)口罩生成器處理的,它使用這些界標(biāo)將口罩放在臉上?,F(xiàn)在我們有了帶有成對(duì)圖像(戴和不戴口罩)的數(shù)據(jù)集,我們就可以繼續(xù)定義 ML 模型的架構(gòu)了。管道的最后一部分是找到最佳損失函數(shù)和組成各個(gè)部分的所有必要腳本,以便我們可以訓(xùn)練和評(píng)估模型。
2. 數(shù)據(jù)生成
要想訓(xùn)練這個(gè)深度學(xué)習(xí)模型,我們需要采用大量數(shù)據(jù),也就是大量輸入和輸出的圖像對(duì)。當(dāng)然,要收集每個(gè)人戴口罩 / 不戴口罩的輸入和輸出圖像是不切實(shí)際的。
當(dāng)前,市面上有很多人臉圖像數(shù)據(jù)集,主要用于訓(xùn)練人臉檢測(cè)算法。我們可以采用這樣的數(shù)據(jù)集,在人臉上繪制口罩——于是我們就有了圖像對(duì)。
我們嘗試了兩個(gè)數(shù)據(jù)集。其中一個(gè)數(shù)據(jù)庫(kù)是馬薩諸塞大學(xué)[1] 的現(xiàn)實(shí)世界人臉標(biāo)記數(shù)據(jù)集。這里是它的 104MB gzip 壓縮 tar 文件,其中包含整個(gè)數(shù)據(jù)集,超過(guò) 5,000 張圖片。這個(gè)數(shù)據(jù)集非常適合我們的情況,因?yàn)樗膱D像主要都是人臉。但對(duì)于最終結(jié)果,我們使用了 CelebA 數(shù)據(jù)集,它更大(200,000 個(gè)樣本),并且包含更高質(zhì)量的圖像。
接下來(lái),我們需要定位面部界標(biāo),以便將口罩放置在正確的位置。為此,我們使用了一個(gè)預(yù)訓(xùn)練的 dlib 面部界標(biāo)檢測(cè)器。你可以使用其他任何類似的數(shù)據(jù)集,只要確保你可以找到預(yù)計(jì)算的面部界標(biāo)點(diǎn)或自己計(jì)算界標(biāo)。
3. 口罩生成器
一開(kāi)始,我們做了一個(gè)口罩生成器的簡(jiǎn)單實(shí)現(xiàn),將一個(gè)多邊形放置在臉上,使多邊形頂點(diǎn)與面部界標(biāo)的距離隨機(jī)化。這樣我們就可以快速生成一個(gè)簡(jiǎn)單的數(shù)據(jù)集,并測(cè)試項(xiàng)目背后的想法是否可行。一旦確定它確實(shí)有效,我們就開(kāi)始尋找一種更強(qiáng)大的解決方案,以更好地反映現(xiàn)實(shí)場(chǎng)景。
GitHub 上有一個(gè)很棒的項(xiàng)目 Mask The Face,已經(jīng)解決了口罩生成問(wèn)題。它從臉部界標(biāo)點(diǎn)估計(jì)口罩位置,估計(jì)臉部?jī)A斜角度以從數(shù)據(jù)庫(kù)中選擇最合適的口罩,最后將口罩放置在臉上。可用的口罩?jǐn)?shù)據(jù)庫(kù)包括了手術(shù)口罩、有各種顏色和紋理的布口罩、幾種呼吸器,甚至是防毒面罩。
import matplotlib.pyplot as plt import matplotlib.image as mpimg from utils.data_generator import DataGenerator from utils.configuration import Configuration # You can update configuration.json to change behavior of the generator configuration = Configuration() dg = DataGenerator(configuration) # Generate images dg.generate_images() # Plot a few examples of image pairs n_examples = 5 inputs, outputs = dg.get_dataset_examples(n_examples) f, axarr = plt.subplots(2, n_examples, figsize=(20,10)) for i in range(len(inputs)): axarr[1, i].imshow(mpimg.imread(inputs[i])) axarr[0, i].imshow(mpimg.imread(outputs[i]4. 架構(gòu)
現(xiàn)在我們已經(jīng)準(zhǔn)備好了數(shù)據(jù)集,是時(shí)候搭建深度神經(jīng)網(wǎng)絡(luò)模型架構(gòu)了。在這項(xiàng)工作中,絕對(duì)沒(méi)有人可以聲稱有一個(gè)客觀的“最佳”選項(xiàng)。
選擇合適架構(gòu)的過(guò)程總是取決于許多因素,例如時(shí)間要求(你要實(shí)時(shí)處理視頻還是要離線預(yù)處理一批圖像?)、硬件需求(模型應(yīng)在搭載高性能 GPU 的群集上運(yùn)行,還是要在低功耗移動(dòng)設(shè)備上運(yùn)行?)等等。每次你都要尋找正確的參數(shù),并針對(duì)你的具體情況進(jìn)行設(shè)置。
5. 卷積神經(jīng)網(wǎng)絡(luò)
卷積神經(jīng)網(wǎng)絡(luò)(CNN)是一種利用卷積核過(guò)濾器的神經(jīng)網(wǎng)絡(luò)架構(gòu)。它適用于各種問(wèn)題,例如時(shí)間序列分析、自然語(yǔ)言處理和推薦系統(tǒng),但主要用于各種圖像相關(guān)的用途,例如對(duì)象分類、圖像分割、圖像分析和圖像修復(fù)。
CNN 的核心是能夠檢測(cè)輸入圖像視覺(jué)特征的卷積層。當(dāng)我們一層層堆疊多個(gè)卷積層時(shí),它們傾向于檢測(cè)不同的特征。第一層通常會(huì)提取更復(fù)雜的特征,例如邊角或邊緣。當(dāng)你深入 CNN 時(shí),卷積層將開(kāi)始檢測(cè)更高級(jí)的特征,例如對(duì)象、面部等。
CNN 架構(gòu)示例
上圖顯示了用于圖像檢測(cè)的 CNN 示例。這并不是我們要解決的問(wèn)題,但 CNN 架構(gòu)是任何修復(fù)架構(gòu)的必要組成部分。
6.ResNet 塊
在討論修復(fù)架構(gòu)之前,我們先來(lái)談?wù)勂鹱饔玫臉?gòu)建塊,它們稱為 ResNet 塊或殘差塊。在傳統(tǒng)的神經(jīng)網(wǎng)絡(luò)或 CNN 中,每一層都連接到下一層。在具有殘差塊的網(wǎng)絡(luò)中,每一層也會(huì)連接到下一層,但還會(huì)再連接兩層或更多層。我們引入了 ResNet 塊以進(jìn)一步提高性能,后文會(huì)具體介紹。
ResNet 構(gòu)建塊 [7]
神經(jīng)網(wǎng)絡(luò)能夠估計(jì)任何函數(shù),我們可以認(rèn)為增加層數(shù)可以提高估計(jì)的準(zhǔn)確性。但由于諸如梯度消失或維數(shù)詛咒之類的問(wèn)題,層數(shù)增加到一定程度就不會(huì)繼續(xù)提升性能了,甚至?xí)屝阅艿雇恕_@就是為什么有很多研究致力于解決這些問(wèn)題,而性能最好的解決方案之一就是殘差塊。
殘差塊允許使用跳過(guò)連接或標(biāo)識(shí)函數(shù),將信息從初始層傳遞到下一層。通過(guò)賦予神經(jīng)網(wǎng)絡(luò)使用標(biāo)識(shí)函數(shù)的能力,相比單純地增加層數(shù),我們可以構(gòu)建性能更好的網(wǎng)絡(luò)。你可以在參考資料中閱讀有關(guān) ResNet 及其變體的更多信息。[8]
7. 編碼器 - 解碼器
編碼器 - 解碼器架構(gòu)由兩個(gè)單獨(dú)的神經(jīng)網(wǎng)絡(luò)組成:編碼器提取輸入(嵌入)的一個(gè)固定長(zhǎng)度表示,而解碼器從該表示生成輸出。
用于圖像分割的編碼器 - 解碼器網(wǎng)絡(luò) [6]
你會(huì)注意到,編碼器部分與上一節(jié)中描述的 CNN 非常相似。經(jīng)過(guò)驗(yàn)證的分類 CNN 通常用作編碼器的基礎(chǔ),甚至直接用作編碼器,只是沒(méi)有最后一個(gè)(分類)層。這個(gè)架構(gòu)可以用來(lái)生成新圖像,這正是我們所需要的。但它的性能卻不是那么好,因此我們來(lái)看一下更好的東西。
8.U-net
U-net 最初是為圖像分割而開(kāi)發(fā)的卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)[2],但它在其他許多任務(wù)(例如圖像修復(fù)或圖像著色)中也展示了自己的能力。
原始文章中的 U-net 架構(gòu) [2]
我們前面之所以提到 ResNet 塊有一個(gè)重要原因。事實(shí)上,將 ResNet 塊與 U-net 架構(gòu)結(jié)合使用對(duì)整體性能的影響最大。你可以在下圖中看到添加 ResNet 塊的架構(gòu)。
U-net 中使用的 Upscale ResNet 塊(頂部)和 downscale resNet 塊(底部)
當(dāng)你將上面的 U-net 架構(gòu)與上一節(jié)中的編碼器 - 解碼器架構(gòu)進(jìn)行比較時(shí),它們看起來(lái)非常相似,但有一個(gè)關(guān)鍵的區(qū)別:U-net 實(shí)現(xiàn)了一種稱為“跳過(guò)連接”的功能,該功能將 identity 從反卷積塊傳播到另一側(cè)對(duì)應(yīng)的上采樣塊(上圖中的灰色箭頭)。這是對(duì)編碼器 - 解碼器架構(gòu)的兩處顯著改進(jìn)。
首先,已知跳過(guò)連接可以加快學(xué)習(xí)過(guò)程并幫助解決梯度消失問(wèn)題[5];其次,它們可以將信息從編碼器直接傳遞到解碼器,從而有助于減少下采樣期間的信息丟失。我們可以認(rèn)為它們能傳播我們希望保持不變的口罩外部圖像的所有部分,同時(shí)還有助于生成口罩下面的臉部圖像。
這正是我們所需要的!跳過(guò)連接將有助于保留我們要傳播到輸出的部分輸入,而 U-net 的編碼器 - 解碼器部分將檢測(cè)到口罩并將其替換為下面的嘴部圖像。
9. 損失函數(shù)
如何選擇損失函數(shù)是你需要解決的最重要的問(wèn)題之一,使用正確的損失函數(shù)可能會(huì)得到性能出色的模型,反之就會(huì)得到令人失望的模型。這就是我們花很多時(shí)間選擇最佳模型的原因所在。下面,我們來(lái)討論幾種選項(xiàng)。
均方誤差(MSE)和均值絕對(duì)誤差(MAE)
MSE 和 MAE 都是損失函數(shù),都基于我們模型生成的圖像將口罩應(yīng)用到面部之前。這似乎正是我們所需要的,但我們并不打算訓(xùn)練可以像素級(jí)完美重現(xiàn)口罩下隱藏內(nèi)容的模型。
我們希望我們的模型理解口罩下面是嘴巴和鼻子,甚至可能要理解來(lái)自那些未被隱藏的事物(例如眼睛)所包含的情感,從而生成悲傷的、快樂(lè)的或可能是驚訝的面孔。這意味著,即使不能完美地捕獲每個(gè)像素,實(shí)際上也可以產(chǎn)生一個(gè)很好的結(jié)果;更重要的是,它可以學(xué)習(xí)如何在任何臉部上泛化,而不僅僅是對(duì)訓(xùn)練數(shù)據(jù)集中的面孔進(jìn)行泛化。
結(jié)構(gòu)相似性指數(shù)(SSIM)
SSIM 是用于度量?jī)蓚€(gè)圖像之間相似度的度量標(biāo)準(zhǔn),由 Wang 等人在 2004 年提出[3]。它專注于解決 MSE/MAE 所存在的問(wèn)題。它提供了一個(gè)數(shù)值表達(dá)式,用來(lái)展示兩張圖像之間的相似度。它通過(guò)對(duì)比圖像之間的三個(gè)測(cè)量值來(lái)做到這一點(diǎn):亮度、對(duì)比度和結(jié)構(gòu)。最終得分是所有三個(gè)測(cè)量值的加權(quán)組合,分?jǐn)?shù)從 0 到 1,1 表示圖像完全相同。
MSE 存在的問(wèn)題:左上圖是未經(jīng)修改的原始圖像;其他圖像均有不同形式的失真。原始圖像與其他圖像之間的均方誤差大致相同(大約 480),而 SSIM 的變化很大。例如,模糊圖像和分割后的圖像與原始圖像的相似度絕對(duì)不如其他圖像,但 MSE 幾乎相同——盡管面部特征和細(xì)節(jié)丟失了。另一方面,偏色圖像和對(duì)比度拉伸的圖像與人眼中的原始圖像非常相似(SSID 指標(biāo)也是一樣),但 MSE 表示不同意這個(gè)結(jié)論。
三、結(jié)果 訓(xùn)練
我們使用 ADAM 優(yōu)化器和 SSIM 損失函數(shù),通過(guò) U-net 架構(gòu)對(duì)模型進(jìn)行訓(xùn)練,將數(shù)據(jù)集分為測(cè)試部分(1,000 張圖像)、訓(xùn)練部分(其余 80%的數(shù)據(jù)集)和驗(yàn)證部分(其余 80%的數(shù)據(jù)集)。我們的第一個(gè)實(shí)驗(yàn)為幾張測(cè)試圖像生成了不錯(cuò)但不太清晰的輸出圖像。是時(shí)候嘗試使用架構(gòu)和損失函數(shù)來(lái)提高性能了,下面是我們嘗試的一些更改:卷積過(guò)濾器的層數(shù)和大小。
更多的卷積過(guò)濾器和更深的網(wǎng)絡(luò)意味著更多的參數(shù)(大小為[8、8、256] 的 2D 卷積層具有 59 萬(wàn)個(gè)參數(shù),大小為[4、4、512] 的層具有 230 萬(wàn)個(gè)參數(shù))和更多的訓(xùn)練時(shí)間。由于每層中過(guò)濾器的深度和數(shù)量是我們模型架構(gòu)的構(gòu)造器的輸入?yún)?shù),因此使用不同的值進(jìn)行實(shí)驗(yàn)非常容易。
嘗試一段時(shí)間后,我們發(fā)現(xiàn)對(duì)我們而言,以下設(shè)置可以達(dá)到性能和模型大小之間的最佳平衡:
# Train model with different number of layers and filter sizes from utils.architectures import UNet from utils.model import Mask2FaceModel # Feel free to experiment with the number of filters and their sizes filters = (64, 128, 128, 256, 256, 512) kernels = ( 7, 7, 7, 3, 3, 3) input_image_size=(256, 256, 3) architecture = UNet.RESNET training_epochs = 20 batch_size = 12 model = Mask2FaceModel.build_model(architecture=architecture, input_size=input_image_size, filters=filters, kernels=kernels) model.summary() model.train(epochs=training_epochs, batch_size=batch_size, loss_function='ssim_l1_loss'
我們做了一些實(shí)驗(yàn),上面代碼塊中的設(shè)置對(duì)我們來(lái)說(shuō)是最好的。
現(xiàn)在,我們已經(jīng)通過(guò)上述調(diào)整對(duì)模型進(jìn)行了訓(xùn)練和調(diào)整,
如你所見(jiàn),給定的網(wǎng)絡(luò)在我們的測(cè)試數(shù)據(jù)上生成了很好的結(jié)果。這個(gè)網(wǎng)絡(luò)具有泛化能力,并且似乎 可以很好地識(shí)別情緒,從而生成微笑或悲傷的面孔。另一方面,這里當(dāng)然也有改進(jìn)的空間。
四、進(jìn)一步改進(jìn)的想法
雖說(shuō)使用 ResNet 塊的 U-net 網(wǎng)絡(luò)效果很好,但我們也可以看到生成的摘口罩圖像不是很清晰。一種解決方法是用一個(gè)提煉網(wǎng)絡(luò)擴(kuò)展我們的網(wǎng)絡(luò),如[4] 中和下圖中所述。此外還可以進(jìn)行其他一些改進(jìn)。
1. 改善數(shù)據(jù)集
根據(jù)我們實(shí)驗(yàn)中獲取的經(jīng)驗(yàn)。數(shù)據(jù)集的選擇可以對(duì)結(jié)果產(chǎn)生重大影響。下一步,我們將合并不同的數(shù)據(jù)集以使樣本具有更大的多樣性,從而更好地模擬現(xiàn)實(shí)世界的數(shù)據(jù)。另一項(xiàng)可行改進(jìn)是調(diào)整將口罩與面部組合的方式,使它們看起來(lái)更自然。[12] 是很好的靈感來(lái)源。
2. 變分自動(dòng)編碼器
我們已經(jīng)提到了編碼器 - 解碼器架構(gòu),其中編碼器部分將輸入圖像映射到嵌入中。我們可以將嵌入視為多維潛在空間中的單點(diǎn)。在許多方面,變分自動(dòng)編碼器與編碼器 - 解碼器是很像的;主要的區(qū)別可能是變分自動(dòng)編碼器的映射是圍繞潛在空間的一點(diǎn)完成的多元正態(tài)分布。這意味著編碼在設(shè)計(jì)上是連續(xù)的,可以實(shí)現(xiàn)更好的隨機(jī)采樣和內(nèi)插。這可能會(huì)極大地改善網(wǎng)絡(luò)輸出生成圖像的平滑度。
3. 生成對(duì)抗網(wǎng)絡(luò)
GAN 能夠生成與真實(shí)照片無(wú)法區(qū)分的結(jié)果,這主要?dú)w功于完全不同的學(xué)習(xí)方法。我們當(dāng)前的模型試圖將訓(xùn)練過(guò)程中的損失降到最低,而 GAN 還是由兩個(gè)獨(dú)立的神經(jīng)網(wǎng)絡(luò)組成:生成器和鑒別器。生成器生成輸出圖像,而鑒別器嘗試確定圖像是真實(shí)圖像還是由生成器生成。
在學(xué)習(xí)過(guò)程中,兩個(gè)網(wǎng)絡(luò)都會(huì)動(dòng)態(tài)更新,讓表現(xiàn)越來(lái)越好,直到最后鑒別器無(wú)法確定所生成的圖像是否真實(shí),生成器所生成的圖像就與真實(shí)圖像無(wú)法區(qū)分了。
GAN 的結(jié)果很好,但在訓(xùn)練過(guò)程中通常會(huì)出現(xiàn)收斂問(wèn)題,而且訓(xùn)練時(shí)間很長(zhǎng)。由于參數(shù)眾多,GAN 模型通常也要復(fù)雜得多,因此不太適合導(dǎo)出到手機(jī)上。
4.Concat ImageNet 和 FaceNet 嵌入
在許多方面,U-net 的瓶頸層都可以用作特征提取嵌入。[10]、[11] 等文章建議,將不同網(wǎng)絡(luò)的嵌入并置可以提高整體性能。
我們嘗試將嵌入(瓶頸層)與 ImageNet 和 FaceNet 的兩種不同嵌入結(jié)合在一起。我們期望這可以添加有關(guān)人臉及其特征的更多信息,以幫助 U-net 的上采樣部分進(jìn)行人臉修復(fù)。這無(wú)疑提高了性能,但另一方面,它使整個(gè)模型更加復(fù)雜,并且與“訓(xùn)練”部分中提到的其他改進(jìn)相比,其性能提升要小得多。
五、總結(jié)
這種人臉重建面臨許多挑戰(zhàn)。我們發(fā)現(xiàn),要想獲得最佳結(jié)果,就需要一種創(chuàng)新的方法來(lái)融合各種數(shù)據(jù)集和技術(shù)。我們必須適當(dāng)?shù)亟鉀Q諸如遮擋、照明和姿勢(shì)多樣性等具體問(wèn)題。問(wèn)題無(wú)法解決的話,在傳統(tǒng)的手工解決方案和深度神經(jīng)網(wǎng)絡(luò)中都會(huì)有顯著的精度下降,方案最后可能只能處理一類照片。
但正是這些挑戰(zhàn)讓我們發(fā)現(xiàn)這個(gè)項(xiàng)目非常具有吸引力。
我們著手創(chuàng)建 Mask2Face 的原因是要為我們的 ML 部門打造一個(gè)典型示例。我們觀察世界上正在發(fā)生的事情(口罩檢測(cè)),并尋找不怎么常見(jiàn)的路徑(摘下口罩)。任務(wù)越難,學(xué)到的經(jīng)驗(yàn)越多。ML 的核心目標(biāo)是解決看似不可能的問(wèn)題,我們希望一直遵循這一理念。
審核編輯:劉清
-
解碼器
+關(guān)注
關(guān)注
9文章
1144瀏覽量
40837 -
編碼器
+關(guān)注
關(guān)注
45文章
3656瀏覽量
134899 -
虛擬機(jī)
+關(guān)注
關(guān)注
1文章
919瀏覽量
28325 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8428瀏覽量
132852 -
python
+關(guān)注
關(guān)注
56文章
4802瀏覽量
84885
原文標(biāo)題:如何利用AI識(shí)別口罩下的人臉?
文章出處:【微信號(hào):vision263com,微信公眾號(hào):新機(jī)器視覺(jué)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論