跟面部識別開愚人玩笑?做一個時尚口罩就能實現
全文共3208字,預計學習時長6分鐘
圖片來源:Upsplash/Pavel Anoshin
目前,人臉識別的使用率正在不斷上升,隨之而來關於面部識別道德問題的爭論也愈發激烈。從機場到社交媒體,面部識別的應用無處不在。因此,想讓自己的臉不被掃描幾乎是不可能的。
對面部識別的理想化攻擊是看起來毫不知情的偽裝。在Hyperface專案的啟發下,本文將介紹一個可穿戴式對抗例項的全過程——詳細介紹建立對抗圖象愚弄選定型別的面部識別,以及如何在面罩上實現例項演示。
面部檢測 VS 面部識別
面部檢測示例(左)vs面部識別示例(右)
對此專案進行深入研究之前,很有必要先明確一下面部檢測與面部識別之間的區別。面部檢測指的是檢測圖象中是否出現人臉的能力。而面部識別首先依靠面部檢測確定圖象中是否出現了人臉,然後進一步確定是誰。
對此專案,我們選擇主攻面部檢測,這主要是因為它更易於檢測。為了更好地測試面部識別,選用面部識別資料庫最好不過了。
面部檢測模型
下一步是選擇建立對抗例項的面部檢測模型。目前使用的面部檢測模型有很多。Vikas Gupta在“Learn OpenCV”平臺上對面部檢測模型及其應用做了全面深入的入門介紹。在此,僅進行簡要回顧。
深度神經網路(DNNs):深度神經網路可以使用輸入的資料集進行訓練,以在各個不同的方向檢測人臉。基於人臉檢測的一種流行的深度神經網路檢測方法是單次多盒檢測器。深度神經網路準確性高且具有普適性。
卷積神經網路(CNNs):卷積神經網路是一種深度神經網路,旨在標註出圖象中不同部分的重要程度。它十分強大,但是在CPU上執行很慢。
Haar級聯分類器:Haar級聯使用一個數據集和大量標記過的積極和消極示例圖片進行訓練。Haar級聯分類器的主要缺點是隻能識別正面照片。由於神經網路更為通用,所以它們無法廣泛應用。
定向梯度直方圖(HOG):定向梯度直方圖是一種面部檢測方法,在將結果輸入支援向量機之前,將經過處理的輸入圖象劃分為具有梯度方向的單元格。定向梯度直方圖檢測快速輕便,但不適用於某些不常見的的面部角度。
將人臉建模為dlib中定向梯度直方圖的示例(感覺可以刪去資料庫,我查了一下感覺和資料庫有區別)
最簡單的攻擊候選模型是定向梯度直方圖。最值得注意的是,定向梯度直方圖的預期輸入易於視覺化並反饋到面部檢測模型中。定向梯度直方圖還有一個優點就是,它的面部視覺化結果不是人類觀察者輕易能看出來的人臉。
Python中的定向梯度直方圖面部檢測
附帶的GitHub儲存庫中提供了具有顯示結果功能的擴充套件程式碼示例。
GitHub庫傳送門:https://github.com/BruceMacD/Adversarial-Faces
測試這些例子需要一個基於定向梯度直方圖(HOG)進行簡單的面部檢測。幸運地是,dlib庫中的正面人臉探測器內建了HOG面部檢測器。
import dlib import cv2 cv2.imread("path/to/input_img.png") frontal_face_detector = dlib.get_frontal_face_detector() upscaling_factor = 1 detected_faces = frontal_face_detector(img, upscaling_factor)
正面人臉探測器執行時需要輸入圖片和放大因子。放大因子為1表示所輸入圖片會放大一次。放大令影象變得更大,並且便於檢測人臉。正面人臉檢測的結果是一個邊界框列表,每個邊界框對應一個被檢測的人臉。
視覺化HOG中使用dlib庫檢測人臉的結果
運用隨機優化建立對抗設計
由於認識到目前HOG預期輸入的視覺化內容會被檢測為正面人臉假陽性,所以需要建立一個設計,列印在看起來不顯眼的口罩上。然而,影響設計的因素有很多,我們並不知道如何優化。人臉的位置、方向和大小都會影響影象中檢測到的面部數量。也可以嘗試不同的設計,直到找到一個好的設計,但是讓學習模型使得這些艱苦工作做起來更加有趣。
研究了強化學習、生成對抗網路和Q—學習後,最終決定使用隨機優化的模擬退火,因為它最適合解決我們的問題,能找到與dlib庫檢測到最多次的人臉相匹配的輸入。
使用Python圖象庫(PIL)和mlrose(用於隨機優化的Python庫)來生成影象並找到最佳狀態。用mlrose優化需要初始狀態和適應度函式。在這個案例中,找到這種最佳狀態需要昂貴的計算,因為生成的狀態需要作為影象儲存到磁碟,以便找到檢測到的人臉數。
# indexes: # 0 % 4 = pos_x # 1 % 4 = pos_y # 2 % 4 = rotation # 3 % 4 = scale initial_state = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
從初始狀態開始,milrose需要一個一維陣列。這意味著必須使用一個黑客解決方案,賦予不同的陣列位置不同的意義(詳見索引解釋)。選擇優化6張人臉的輸入,因為可以一直複製設計以增加其大小。
def detected_max(state): # converts the 1D state array into images get_img_from_state(state) return len(detect_faces(cv2.imread(OUTPUT)))
適應度函式只是將狀態轉換為影象,然後檢測影象中的人臉數量。人臉的數量越多,適應度就越好。我們還可以嘗試根據輸入的HOG人臉影象的大小將適應度函式改得更高。因為在現實生活中,更大的面孔更容易被發現,所以這種效果可能更好。然而,發現考慮人臉大小會耗費更多計算時間,而得到的結果在視覺上是相似的。
fitness = mlrose.CustomFitness(detected_max) problem = mlrose.DiscreteOpt(length=24, fitness_fn=fitness, maximize=True, max_val=scale_factor) schedule = mlrose.ExpDecay() best_state, max_faces = mlrose.simulated_annealing(problem, schedule=schedule, max_attempts=10, max_iters=1000, init_state=initial_state, random_state=1) print('Optimal state found: ', best_state) print('Max fitness found: ', max_faces) # save the optimal found get_img_from_state(best_state) print("Number of faces in output: ", len(detect_faces(cv2.imread(OUTPUT))))
利用適應度和初始狀態集配置milrose進行模擬退火很簡單。分配輸入內容,並讓它執行直到找到一個最佳結果。做幾次這樣的測試,以找到視覺上看起來有趣的結果。
模擬退火狀態下有趣的輸出結果
最後,在這個有趣的輸出中添加了一些最後的潤色,以模糊面部設計——其意圖是愚弄人類。
模糊面部結構的最終設計
在面罩上測試此設計
使用對抗面部設計的原型面罩上檢測到的面部
完成最終的設計後,我設計了一些模擬面具來測試HOG面部檢測如何評估它們。初步結果似乎很有希望,上述設計返回結果始終為4-5個錯誤檢測到的面孔。
AI未來說*青年學術論壇 火熱報名中
留言 點贊 關注
我們一起分享AI學習與發展的乾貨
歡迎關注全平臺AI垂類自媒體 “讀芯術”
(新增小編微信:dxsxbb,加入讀者圈,一起討論最新鮮的人工