找到一個免費的開源工具
https://github.com/FaceOnLive/Realtime-Background-Changer-SDK-Android
他是根據(jù)相機實時摳人像的辣吃,剛好在他的demo里面集成了相機动遭,可以把背景圖片改一下,神得,設置成藍色紅色就是證件照的拍攝了厘惦。(fotoapparat是項目中的相機sdk,哩簿,我運行不起來宵蕉,庫已經(jīng)下載不下來了,所以我去GitHub直接拿了他的源碼)
當然我看有些收費的證件照軟件還支持傳入照片變成證件照节榜,羡玛,那么demo中的代碼就要改一下了。如下:
package com.ttv.segmentdemo
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.ttv.segment.TTVException
import com.ttv.segment.TTVSeg
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
class MainActivity2 : AppCompatActivity() {
private var licenseValid = false
private var humanSegInited = false
private val imageView by lazy {
findViewById<ImageView>(R.id.image_view)
}
private val button by lazy {
findViewById<Button>(R.id.btn_start)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
TTVSeg.createInstance(this)
val ret = TTVSeg.getInstance().setLicenseInfo("")
if(ret == 0) {
licenseValid = true
init()
}
button.setOnClickListener {
// 處理傳入的圖片
lifecycleScope.launch{
val bitmap = withContext(Dispatchers.IO){
processImage()
}
bitmap?.apply {
// 顯示處理結果
imageView.setImageBitmap(this)
}
}
}
}
private fun init() {
if (!licenseValid) {
return
}
try {
if (TTVSeg.getInstance().create(this.applicationContext, 0, 0, 0) == 0) {
humanSegInited = true
return
}
} catch (e: TTVException) {
e.printStackTrace()
}
}
private suspend fun processImage():Bitmap? {
if (!humanSegInited) {
Toast.makeText(this, "人像分割未初始化", Toast.LENGTH_SHORT).show()
return null
}
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.face2) // 替換為你的圖片資源
val bitmapData = bitmapToNV21(bitmap)
val bgColor = intArrayOf(255, 255, 255) // 設置背景顏色
val iArr = IntArray(1)
// 執(zhí)行摳圖
try {
val segment: Bitmap = TTVSeg.getInstance().process(
bitmapData,
bitmap.width,
bitmap.height,
0, // 這里的 rotation 可根據(jù)需要調整
0,
bgColor,
null,
iArr
)
return segment
}catch(e : Error){
e.printStackTrace()
}
return null
}
fun compressBitmap(originalBitmap: Bitmap, quality: Int, width: Int, height:Int): Bitmap {
// 縮放 Bitmap
// 縮放 Bitmap
val resizedBitmap = Bitmap.createScaledBitmap(originalBitmap, width, height, true)
// 創(chuàng)建一個 ByteArrayOutputStream
// 創(chuàng)建一個 ByteArrayOutputStream
val outputStream = ByteArrayOutputStream()
// 壓縮 Bitmap
// 壓縮 Bitmap
resizedBitmap.compress(
Bitmap.CompressFormat.JPEG,
quality,
outputStream
) // quality 范圍是 0 - 100
// 將壓縮后的數(shù)據(jù)轉換為 byte 數(shù)組
// 將壓縮后的數(shù)據(jù)轉換為 byte 數(shù)組
val byteArray = outputStream.toByteArray()
// 通過 byte 數(shù)組創(chuàng)建新的 Bitmap
// 通過 byte 數(shù)組創(chuàng)建新的 Bitmap
return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
}
fun bitmapToNV21(bitmap: Bitmap): ByteArray {
// 1. 將 Bitmap 轉換為 YUV NV21 格式
val width = bitmap.width
val height = bitmap.height
val argb = IntArray(width * height)
bitmap.getPixels(argb, 0, width, 0, 0, width, height)
return argbToNv21(argb, width, height)
}
private fun argbToNv21(argb: IntArray, width: Int, height: Int): ByteArray {
val frameSize = width * height
var yIndex = 0
var uvIndex = frameSize
var index = 0
val nv21 = ByteArray(width * height * 3 / 2)
for (j in 0 until height) {
for (i in 0 until width) {
val R = argb[index] and 0xFF0000 shr 16
val G = argb[index] and 0x00FF00 shr 8
val B = argb[index] and 0x0000FF
val Y = (66 * R + 129 * G + 25 * B + 128 shr 8) + 16
val U = (-38 * R - 74 * G + 112 * B + 128 shr 8) + 128
val V = (112 * R - 94 * G - 18 * B + 128 shr 8) + 128
nv21[yIndex++] = (if (Y < 0) 0 else if (Y > 255) 255 else Y).toByte()
if (j % 2 == 0 && index % 2 == 0 && uvIndex < nv21.size - 2) {
nv21[uvIndex++] = (if (V < 0) 0 else if (V > 255) 255 else V).toByte()
nv21[uvIndex++] = (if (U < 0) 0 else if (U > 255) 255 else U).toByte()
}
++index
}
}
return nv21
}
}
可惜的是宗苍,yuvnv21這種方式摸透了稼稿,直接傳普通bitmap的開放接口傳數(shù)據(jù)會報錯,讳窟,后續(xù)再摸摸让歼。不然的話轉來轉去太耗時了
如果要做開發(fā),傳過去的圖片最好先經(jīng)過一次裁剪丽啡,谋右,先讓用戶選擇好大小,可以4:3裁剪可以16:9碌上,當然1:1也可以倚评。還有,我這里bgColor傳的是白色馏予,證件照嘛天梧,改成藍色或者紅色應該問題不大,就不記錄了
aar保存一下:
鏈接: https://pan.baidu.com/s/1IJ0P35TSnzMzABalC5I2ag 提取碼: p5ik 復制這段內容后打開百度網(wǎng)盤手機App霞丧,操作更方便哦