Firebase ML Kit是一組本地和基於雲的API,用於向移動應用程序添加機器學習功能,最近已得到增強,可支持面部輪廓檢測。由於這個強大的功能,您不再需要在檢測面部時將自己限制為近似矩形。相反,您可以使用大量坐標來準確描述檢測到的面部和面部標誌的形狀,例如眼睛,嘴唇和眉毛。
這使您可以輕鬆創建人工智慧應用程序,可以執行複雜的計算機視覺相關任務,如交換面部,識別情緒或應用數字化妝。
在本教程中,我將向您展示如何使用ML Kit的面部輪廓檢測功能來創建可以突出顯示照片中面部的Android應用程序。
要充分利用本教程,您必須具有以下許可權:
由於ML Kit是Firebase平台的一部分,因此您需要一個Firebase項目才能在Android Studio項目中使用它。要創建一個,請轉到「 工具」>「Firebase」以啟動Firebase助手。
接下來,打開「 分析」 部分,然後按「 連接」 按鈕。在彈出的對話框中,鍵入新Firebase項目的名稱,選擇您所在的國家/地區,然後按「 連接」 按鈕。
成功連接後,按「 將分析添加到應用程序」 按鈕,以便助理可以在Android Studio項目中進行所有必要的與Firebase相關的配置更改。
此時,如果您打開app 模塊的build.gradle 文件以及其他更改,您應該看到其中implementation 存在以下依賴項:
app
implementation
implementation com.google.firebase:firebase-core:16.0.4
為了能夠使用ML Kit的面部輪廓檢測功能,您還需要兩個依賴項:一個用於最新版本的ML Vision庫,另一個用於ML Vision面部模型。以下是添加它們的方法:
implementation com.google.firebase:firebase-ml-vision:18.0.1 implementation com.google.firebase:firebase-ml-vision-face-model:17.0.2
在本教程中,您將使用遠程圖像。為便於下載和顯示此類圖像,請為Picasso庫添加依賴項:
implementation com.squareup.picasso:picasso:2.71828
ML Kit的面部輪廓檢測始終在用戶設備上本地運行。默認情況下,在用戶首次打開應用程序時會自動下載進行面部輪廓檢測的機器學習模型。但是,為了改善用戶體驗,我建議您在用戶安裝應用後立即開始下載。為此,請將以下 <meta-data> 標記添加到AndroidManifest.xml 文件中:
<meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="face" />
您將在應用程序的布局中需要三個小部件:EditText 用戶可以在其中鍵入在線照片的URL的ImageView 小部件,用於顯示照片的Button 小部件以及用於啟動面部輪廓檢測過程的 小部件。此外,您還需要一個 RelativeLayout 小部件來定位三個小部件。因此,將以下代碼添加到主活動的布局XML文件中:
`<``RelativeLayout`
`xmlns:android``=``"[http://schemas.android.com/apk/res/android](http://schemas.android.com/apk/res/android)"`
`android:layout_width``=``"match_parent"`
`android:layout_height``=``"match_parent"`
`android:padding``=``"16dp"``>`
`<``EditText` `android:layout_width``=``"match_parent"`
`android:layout_height``=``"wrap_content"`
`android:hint``=``"Image URL"`
`android:imeOptions``=``"actionGo"`
`android:inputType``=``"textUri"`
`android:id``=``"@+id/user_input"` `/>`
`<``Button` `android:layout_width``=``"match_parent"`
`android:text``=``"Detect contours"`
`android:layout_alignParentBottom``=``"true"`
`android:id``=``"@+id/action_button"` `/>`
`<``ImageView` `android:layout_width``=``"match_parent"`
`android:id``=``"@+id/photo"`
`android:layout_below``=``"@+id/user_input"`
`android:layout_above``=``"@id/action_button"`
`android:scaleType``=``"centerCrop"``/>`
`</``RelativeLayout``>`
使用Picasso庫,下載和顯示遠程圖像只需要調用兩種方法。首先,調用load() 方法以指定要下載的圖像的URL,然後調用該into() 方法以指定ImageView 要在其中顯示下載圖像的窗口小部件。
當然,只有在用戶輸入URL後才能調用這兩種方法。因此,請確保在OnEditorActionListener 附加到EditText 上一步中創建的窗口小部件的對象中調用它們。以下代碼顯示了如何執行此操作:
user_input.setOnEditorActionListener { _, action, _ -> if(action == EditorInfo.IME_ACTION_GO) { Picasso.get() .load(user_input.text.toString()) .into(photo) true } false }
立即運行應用程序並嘗試鍵入有效的圖像URL以確保其正常工作。
您將在附加到Button 布局窗口小部件的單擊事件處理程序中運行所有面部輪廓檢測操作。因此,在繼續之前,請將以下代碼添加到您的活動:
action_button.setOnClickListener {
// Rest of the code goes here
}
為了能夠處理面部數據,您現在必須創建一個 FirebaseVisionFaceDetector 對象。但是,由於默認情況下它不會檢測面的輪廓,因此您還必須創建一個FirebaseVisionFaceDetectorOptions 可以對其進行配置的對象。
要創建有效的選項對象,必須遵循構建器模式。因此,創建FirebaseVisionFaceDetectorOptions.Builder 類的實例,調用其 setContourMode() 方法,並將ALL_CONTOURS 常量傳遞給它,以指定您要檢測圖像中存在的所有面的輪廓。
然後調用build() 構建器的方法來生成選項對象。
val detectorOptions = FirebaseVisionFaceDetectorOptions.Builder() .setContourMode( FirebaseVisionFaceDetectorOptions.ALL_CONTOURS ).build()
您現在可以將選項對象傳遞給getVisionFaceDetector() ML Kit FirebaseVision 類的方法來創建面部輪廓檢測器。
val detector = FirebaseVision .getInstance() .getVisionFaceDetector(detectorOptions)
面部輪廓檢測器無法直接使用ImageView 窗口小部件顯示的照片 。相反,它希望您將FirebaseVisionImage 對象傳遞給它。要生成此類對象,必須將照片轉換為Bitmap 對象。以下代碼顯示了如何執行此操作:
val visionImage = FirebaseVisionImage.fromBitmap( (photo.drawable as BitmapDrawable).bitmap )
您現在可以調用detectInImage() 檢測器的方法來檢測照片中存在的所有面部的輪廓。該方法以非同步方式運行,並在FirebaseVisionFace 成功完成後返回對象列表 。
detector.detectInImage(visionImage).addOnSuccessListener { // More code here }
在on-success偵聽器中,您可以使用it 隱式變數來遍歷檢測到的面部列表。每個面都有大量與之相關的輪廓點。要訪問這些點,您必須調用該getContour() 方法。該方法可以返回幾個不同面部標誌的輪廓點。例如,如果將常量傳遞 LEFT_EYE 給它,它將返回左眼輪廓所需的點。同樣,如果你傳遞UPPER_LIP_TOP 給它,你將得到與上唇頂邊相關的點。
在本教程中,我們將使用FACE 常量,因為我們想要突出顯示面部本身。以下代碼顯示如何列印沿每個面邊緣存在的所有點的X和Y坐標:
it.forEach { val contour = it.getContour(FirebaseVisionFaceContour.FACE) contour.points.forEach { println("Point at ${it.x}, ${it.y}") } // More code here }
如果您現在嘗試使用該應用程序並指定其中至少有一個面部的圖像,您應該在Logcat 窗口中看到類似的內容:
要突出顯示檢測到的面部,讓我們使用輪廓點簡單地繪製它們周圍的路徑。為了能夠繪製這樣的路徑,您需要一個ImageView 小部件點陣圖的可變副本。通過調用其copy() 方法創建一個。
ImageView
copy()
val mutableBitmap = (photo.drawable as BitmapDrawable).bitmap.copy( Bitmap.Config.ARGB_8888, true )
通過直接修改點陣圖的像素來繪製路徑可能很困難。因此,通過將它傳遞給Canvas 類的構造函數,為它創建一個新的2D畫布 。
此外,創建一個Paint 對象以指定要在畫布上繪製的像素的顏色。以下代碼顯示如何創建可在其上繪製半透明紅色像素的畫布:
val canvas = Canvas(mutableBitmap)
val myPaint = Paint(Paint.ANTI_ALIAS_FLAG) myPaint.color = Color.parseColor("#99ff0000")
在畫布上繪製路徑的最簡單方法是使用Path 該類。通過使用類的直觀命名 moveTo() 和lineTo() 方法,您可以輕鬆地在畫布上繪製複雜的形狀。
現在,要繪製一個面的形狀,請調用該moveTo() 方法一次,並將第一個輪廓點的坐標傳遞給它。通過這樣做,您可以指定路徑的開始位置。然後將所有點的坐標傳遞給lineTo() 方法以實際繪製路徑。最後,調用close() 方法關閉路徑並填充它。
因此,添加以下代碼:
val path = Path() path.moveTo(contour.points[0].x, contour.points[0].y) contour.points.forEach { path.lineTo(it.x, it.y) } path.close()
要渲染路徑,請將其drawPath() 與Paint對象一起傳遞給畫布的方法。
canvas.drawPath(path, myPaint)
要更新ImageView 窗口小部件以顯示修改後的點陣圖,請將點陣圖傳遞給其setImageBitmap() 方法。
photo.setImageBitmap(mutableBitmap)
如果你現在運行應用程序,你應該能夠看到它在它檢測到的所有面上繪製半透明的紅色蒙版。
遲來的祝福,大家新年快樂哦
TAG:Android | Android開發 | Android應用 |