|
|
|
@@ -0,0 +1,511 @@ |
|
|
|
package com.aispeech.nativedemo.tengine2 |
|
|
|
|
|
|
|
import android.app.Activity |
|
|
|
import android.graphics.Bitmap |
|
|
|
import android.graphics.Rect |
|
|
|
import android.util.Log |
|
|
|
import com.aispeech.nativedemo.MainActivity |
|
|
|
import com.aispeech.nativedemo.asr.observer.DuiMessageObserver |
|
|
|
import com.aispeech.nativedemo.entity.PersonInfo |
|
|
|
import com.aispeech.nativedemo.face.AngleInfo |
|
|
|
import com.aispeech.nativedemo.face.FaceCheckInterface |
|
|
|
import com.aispeech.nativedemo.face.FaceManager |
|
|
|
import com.aispeech.nativedemo.log.Logger |
|
|
|
import com.aispeech.nativedemo.utils.Utils |
|
|
|
import com.lenovo.lefacecamerademo.ConfigClass.PROGRAM_ROOT_PATH |
|
|
|
import com.lenovo.lefacesdk.MultiAtt |
|
|
|
import com.shareopen.library.MVVM.application.AppContext |
|
|
|
import com.shareopen.library.helper.LogUtils |
|
|
|
import com.tenginekit.AndroidConfig |
|
|
|
import com.tenginekit.KitCore |
|
|
|
import com.tenginekit.face.Face |
|
|
|
import com.tenginekit.face.FaceDetectInfo |
|
|
|
import com.tenginekit.face.FaceLandmarkInfo |
|
|
|
import com.tenginekit.model.TenginekitPoint |
|
|
|
import java.io.File |
|
|
|
import java.nio.ByteBuffer |
|
|
|
import java.util.concurrent.ArrayBlockingQueue |
|
|
|
import java.util.concurrent.ConcurrentLinkedQueue |
|
|
|
|
|
|
|
|
|
|
|
class TEngine2FaceCheckManager : FaceCheckInterface { |
|
|
|
|
|
|
|
companion object { |
|
|
|
val instance by lazy (LazyThreadSafetyMode.SYNCHRONIZED){ |
|
|
|
TEngine2FaceCheckManager() |
|
|
|
} |
|
|
|
const val LOG_TAG = "TengineKitApp" |
|
|
|
} |
|
|
|
var hasInitKs = false |
|
|
|
private val TAG = "KSFaceCheckManager" |
|
|
|
var needKSCheck = false |
|
|
|
|
|
|
|
@Volatile |
|
|
|
var faceCount = 0 |
|
|
|
var faceQueue = ArrayBlockingQueue<PersonInfo>(10) |
|
|
|
var faceListInVad = ConcurrentLinkedQueue<FaceLandmarkInfo?>() |
|
|
|
var faceStrListInVad = ConcurrentLinkedQueue<String>() |
|
|
|
var faceRectListInVad = ConcurrentLinkedQueue<MultiAtt>() |
|
|
|
|
|
|
|
|
|
|
|
var faceListCloseInVad = ConcurrentLinkedQueue<FaceLandmarkInfo?>() |
|
|
|
var faceStrListCloseInVad = ConcurrentLinkedQueue<String>() |
|
|
|
var faceRectListCloseInVad = ConcurrentLinkedQueue<MultiAtt>() |
|
|
|
|
|
|
|
var needFaceCheck = true |
|
|
|
var needFaceAngleCheck = true |
|
|
|
|
|
|
|
// fun getInstance(): TEngineFaceCheckManager? { |
|
|
|
// if (TEngineFaceCheckManager.mInstance == null) { |
|
|
|
// synchronized(KSFaceCheckManager::class.java) { |
|
|
|
// if (TEngineFaceCheckManager.mInstance == null) { |
|
|
|
// TEngineFaceCheckManager.mInstance = TEngineFaceCheckManager() |
|
|
|
// } |
|
|
|
// } |
|
|
|
// } |
|
|
|
// return TEngineFaceCheckManager.mInstance |
|
|
|
// } |
|
|
|
|
|
|
|
override fun init() { |
|
|
|
Log.i(LOG_TAG, "start init") |
|
|
|
/** |
|
|
|
* 初始化 |
|
|
|
* */ |
|
|
|
KitCore.init( |
|
|
|
AppContext.getInstance(), |
|
|
|
AndroidConfig |
|
|
|
.create() |
|
|
|
.setNormalMode() |
|
|
|
.setDefaultFunc() |
|
|
|
.setInputImageFormat(AndroidConfig.ImageFormat.RGBA)) |
|
|
|
// .setInputImageSize(Image_w, Image_h) |
|
|
|
// .setOutputImageSize(Image_w as Int, Image_h as Int) |
|
|
|
Log.i(LOG_TAG, "init Success") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
override fun bitmapDetected(bitmap: Bitmap?, personInfo: PersonInfo) { |
|
|
|
if (!needKSCheck || !hasInitKs) { |
|
|
|
return |
|
|
|
} |
|
|
|
if (personInfo.result == null || DuiMessageObserver.needPause) { |
|
|
|
return |
|
|
|
} |
|
|
|
val start = System.currentTimeMillis() |
|
|
|
val bitmap1 = Utils.CompressBmpByHD(bitmap, personInfo.result) |
|
|
|
?: return |
|
|
|
personInfo.faceStr = "" |
|
|
|
val faceResult = doDetect(bitmap1, personInfo) |
|
|
|
if (faceResult != null) { |
|
|
|
addFaceInVad(faceResult, personInfo.faceStr, personInfo.result) |
|
|
|
} else { |
|
|
|
LogUtils.e( |
|
|
|
"testface", |
|
|
|
" faceData.faceResult == null $personInfo" |
|
|
|
) |
|
|
|
} |
|
|
|
// faceQueue.offer(personInfo); |
|
|
|
// faceCount++; |
|
|
|
Log.e( |
|
|
|
"testtwo", |
|
|
|
"selectMan CompressBmpByHD duration " + (System.currentTimeMillis() - start) |
|
|
|
) |
|
|
|
if (MainActivity.instance != null) { |
|
|
|
MainActivity.instance.setSettingLog(personInfo.faceStr) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
override fun bitmapDetectedClose(bitmap: Bitmap?, personInfo: PersonInfo) { |
|
|
|
if (!needKSCheck || !hasInitKs) { |
|
|
|
return |
|
|
|
} |
|
|
|
if (personInfo.result == null || DuiMessageObserver.needPause) { |
|
|
|
LogUtils.e("testtwo", " personInfo.result == null$personInfo") |
|
|
|
return |
|
|
|
} |
|
|
|
val start = System.currentTimeMillis() |
|
|
|
val bitmap1 = Utils.CompressBmpByHD(bitmap, personInfo.result) |
|
|
|
?: return |
|
|
|
personInfo.faceStr = "" |
|
|
|
val faceResult = doDetect(bitmap1, personInfo) |
|
|
|
val time = System.currentTimeMillis() |
|
|
|
if (faceResult != null) { |
|
|
|
addFaceInVadClose(faceResult, personInfo.faceStr, personInfo.result) |
|
|
|
} else { |
|
|
|
LogUtils.e( |
|
|
|
"testtwo", |
|
|
|
" faceData.faceResult == null $personInfo" |
|
|
|
) |
|
|
|
val file: File = |
|
|
|
File(PROGRAM_ROOT_PATH + "/" + DuiMessageObserver.mTime + "_" + personInfo.faceWidth + "_" + time + "_" + "last.jpg") |
|
|
|
//BitmapUtil.saveBitmap(file.getAbsolutePath(), bitmap1); |
|
|
|
} |
|
|
|
// faceQueue.offer(personInfo); |
|
|
|
// faceCount++; |
|
|
|
Log.e("testtwo", "close man face width " + personInfo.faceWidth + " time " + time) |
|
|
|
Log.e( |
|
|
|
"testtwo", |
|
|
|
"close CompressBmpByHD duration " + (System.currentTimeMillis() - start) + " facestr " + personInfo.faceStr + " person " + personInfo + " time " + time |
|
|
|
) |
|
|
|
if (MainActivity.instance != null) { |
|
|
|
MainActivity.instance.setSettingLogClose(personInfo.faceStr) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
override fun onVadBegin() { |
|
|
|
while (faceListInVad.size > 2) { |
|
|
|
faceListInVad.poll() |
|
|
|
} |
|
|
|
Log.e("testface", "before vad " + faceListInVad.size) |
|
|
|
} |
|
|
|
|
|
|
|
override fun setFaceCheck(faceCheck: Boolean, |
|
|
|
needMouthCheck: Boolean, |
|
|
|
needAngleCheck: Boolean) { |
|
|
|
needKSCheck = faceCheck |
|
|
|
needFaceCheck = needMouthCheck |
|
|
|
needFaceAngleCheck = needAngleCheck; |
|
|
|
|
|
|
|
Log.i(LOG_TAG, "setFaceCheck ") |
|
|
|
} |
|
|
|
|
|
|
|
override fun getAngle(bitmap: Bitmap?, personInfo: PersonInfo?): AngleInfo? { |
|
|
|
return null |
|
|
|
} |
|
|
|
|
|
|
|
fun doDetect(bitmap: Bitmap, personInfo: PersonInfo) : FaceLandmarkInfo? { |
|
|
|
val start = System.currentTimeMillis() |
|
|
|
var faceResult : FaceLandmarkInfo? = null; |
|
|
|
bitmap?.let { |
|
|
|
/** |
|
|
|
* 获取人脸信息 |
|
|
|
*/ |
|
|
|
/** |
|
|
|
* 获取人脸信息 |
|
|
|
*/ |
|
|
|
val data: ByteArray = bitmap2Bytes(bitmap) |
|
|
|
val faceDetect = Face.detect(data) |
|
|
|
var faceDetectInfos: List<FaceDetectInfo>? = ArrayList() |
|
|
|
var landmarkInfos: List<FaceLandmarkInfo> = ArrayList() |
|
|
|
if (faceDetect.faceCount > 0) { |
|
|
|
faceDetectInfos = faceDetect.detectInfos |
|
|
|
landmarkInfos = faceDetect.landmark2d() |
|
|
|
} |
|
|
|
|
|
|
|
Log.d("#####", "Face Num: " + faceDetectInfos!!.size) |
|
|
|
if (faceDetectInfos != null && faceDetectInfos.size > 0) { |
|
|
|
val face_landmarks: List<List<TenginekitPoint>> = ArrayList() |
|
|
|
for (i in faceDetectInfos.indices) { |
|
|
|
var rect: Rect? = Rect() |
|
|
|
rect = faceDetectInfos[i].asRect() |
|
|
|
Log.d( |
|
|
|
"#####", |
|
|
|
"mouseClose: " + landmarkInfos[i].mouseClose + "pitch: " + landmarkInfos[i].pitch + "yaw: " + landmarkInfos[i].yaw |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
Log.i(LOG_TAG, "end detect") |
|
|
|
val sb = StringBuilder() |
|
|
|
if (landmarkInfos != null) { |
|
|
|
LogUtils.e("access123", "faces length " + landmarkInfos.size) |
|
|
|
for (face in landmarkInfos) { |
|
|
|
var expression = "" |
|
|
|
sb.append("· ").append("表情:").append(expression).append("\n") |
|
|
|
sb.append("· ").append("眼部状态(左眼):").append(face.leftEyeClose) |
|
|
|
.append("\n") |
|
|
|
sb.append("· ").append("眼部状态(右眼):").append(face.rightEyeClose) |
|
|
|
.append("\n") |
|
|
|
sb.append("· ").append("嘴部状态:").append("闭嘴${(face.mouseClose*100).toInt()}%") |
|
|
|
.append("\n") |
|
|
|
sb.append("· ").append("嘴部状态bigopen:").append("闭嘴${(face.mouseOpenBig*100).toInt()}%") |
|
|
|
.append("\n") |
|
|
|
sb.append("· ").append("3DPose:{pitch=").append(face.pitch).append(",roll=") |
|
|
|
.append(face.roll).append(",yaw=").append(face.yaw).append("}\n") |
|
|
|
sb.append("· ").append("关键点个数:").append("" + face.landmarks.size).append("\n") |
|
|
|
sb.append("\n") |
|
|
|
Log.e(LOG_TAG, "bitmapDetected: $sb") |
|
|
|
faceResult = face |
|
|
|
} |
|
|
|
} |
|
|
|
val faceStr = sb.toString() |
|
|
|
personInfo.faceStr = faceStr |
|
|
|
LogUtils.e("access123", "faceStr $faceStr") |
|
|
|
LogUtils.e( |
|
|
|
"testface", |
|
|
|
"face duration " + (System.currentTimeMillis() - start) + " lx x1 " + personInfo.result.fa_x1 + " lx y1 " + personInfo.result.fa_y1 + " lx w " + personInfo.result.fa_w + " lx h " + personInfo.result.fa_h |
|
|
|
) |
|
|
|
} |
|
|
|
return faceResult; |
|
|
|
} |
|
|
|
|
|
|
|
private fun bitmap2Bytes(image: Bitmap): ByteArray { |
|
|
|
// calculate how many bytes our image consists of |
|
|
|
val bytes = image.byteCount |
|
|
|
val buffer = ByteBuffer.allocate(bytes) // Create a new buffer |
|
|
|
image.copyPixelsToBuffer(buffer) // Move the byte data to the buffer |
|
|
|
return buffer.array() |
|
|
|
} |
|
|
|
|
|
|
|
private fun getEyeStatus(eyeType: Int): String? { |
|
|
|
var reuslt = "" |
|
|
|
when (eyeType) { |
|
|
|
0 -> reuslt = "不戴眼镜,并且睁着眼" |
|
|
|
1 -> reuslt = "不戴眼镜,并且闭着眼" |
|
|
|
2 -> reuslt = "戴着普通眼镜,并且睁着眼" |
|
|
|
3 -> reuslt = "戴着普通眼镜,并且闭着眼" |
|
|
|
4 -> reuslt = "戴着墨镜" |
|
|
|
5 -> reuslt = "眼镜被遮挡" |
|
|
|
} |
|
|
|
return reuslt |
|
|
|
} |
|
|
|
|
|
|
|
private fun getMouthStatus(mouthStatus: Int): String? { |
|
|
|
var result = "" |
|
|
|
when (mouthStatus) { |
|
|
|
0 -> result = "带着面具或者带着口罩" |
|
|
|
1 -> result = "被其他东西遮挡着嘴巴" |
|
|
|
2 -> result = "闭嘴状态" |
|
|
|
3 -> result = "张嘴状态" |
|
|
|
} |
|
|
|
return result |
|
|
|
} |
|
|
|
|
|
|
|
fun addFaceInVad(faceResult: FaceLandmarkInfo?, faceStr: String?, faceMultiAtt: MultiAtt?) { |
|
|
|
faceListInVad.offer(faceResult) |
|
|
|
faceStrListInVad.offer(faceStr) |
|
|
|
faceRectListInVad.offer(faceMultiAtt) |
|
|
|
} |
|
|
|
|
|
|
|
fun addFaceInVadClose( |
|
|
|
faceResult: FaceLandmarkInfo?, |
|
|
|
faceStr: String?, |
|
|
|
faceMultiAtt: MultiAtt? |
|
|
|
) { |
|
|
|
faceListCloseInVad.offer(faceResult) |
|
|
|
faceStrListCloseInVad.offer(faceStr) |
|
|
|
faceRectListCloseInVad.offer(faceMultiAtt) |
|
|
|
} |
|
|
|
|
|
|
|
override fun getCurrentSpeakBeforeASR(name: String): Boolean { |
|
|
|
if (!needKSCheck || !hasInitKs) { |
|
|
|
return true |
|
|
|
} |
|
|
|
if (!needFaceCheck) { |
|
|
|
return if (!needFaceAngleCheck) { |
|
|
|
true |
|
|
|
} else { |
|
|
|
checkAngle(faceListInVad, name) |
|
|
|
} |
|
|
|
} |
|
|
|
if (faceListInVad.size == 0) { |
|
|
|
Log.e("testface", "BeforeASR size 0 is speak false") |
|
|
|
return false |
|
|
|
} |
|
|
|
if (needFaceAngleCheck) { |
|
|
|
val isAngleOk = checkAngle(faceListInVad, name) |
|
|
|
if (!isAngleOk) { |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
return checkSpeak(name, " BeforeASR ", faceListInVad) |
|
|
|
} |
|
|
|
|
|
|
|
override fun onDestroy() { |
|
|
|
KitCore.release() |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
override fun getCurrentSpeak(name: String, isClear: Boolean): Boolean { |
|
|
|
Log.e("testkd2", "FaceManager.needKSCheck " + needKSCheck) |
|
|
|
if (!needKSCheck || !hasInitKs) { |
|
|
|
return true |
|
|
|
} |
|
|
|
if (!needFaceCheck) { |
|
|
|
return if (!needFaceAngleCheck) { |
|
|
|
true |
|
|
|
} else { |
|
|
|
val isRightAngle = checkAngle(faceListInVad, name) |
|
|
|
faceListInVad.clear() |
|
|
|
faceStrListInVad.clear() |
|
|
|
faceRectListInVad.clear() |
|
|
|
isRightAngle |
|
|
|
} |
|
|
|
} |
|
|
|
if (faceListInVad.size == 0) { |
|
|
|
Log.e("testface2", "close size 0 is speak false") |
|
|
|
return false |
|
|
|
} |
|
|
|
if (needFaceAngleCheck) { |
|
|
|
val isAngleOk = checkAngle(faceListInVad, name) |
|
|
|
Log.e("testtwoface", "$name isAngleOk $isAngleOk") |
|
|
|
if (!isAngleOk) { |
|
|
|
faceListInVad.clear() |
|
|
|
faceStrListInVad.clear() |
|
|
|
faceRectListInVad.clear() |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
//needPause = true; |
|
|
|
val start = System.currentTimeMillis() |
|
|
|
//if (FaceManager.faceCount == 1 && faceListInVad.size() < 20) |
|
|
|
run {} |
|
|
|
// while (FaceManager.faceCount != 0) { |
|
|
|
// try { |
|
|
|
// Thread.sleep(20); |
|
|
|
// } catch (InterruptedException e) { |
|
|
|
// throw new RuntimeException(e); |
|
|
|
// } |
|
|
|
// } |
|
|
|
val isSpeak = checkSpeak(name, "closeMan", faceListInVad) |
|
|
|
if (!isSpeak) { |
|
|
|
} |
|
|
|
faceListInVad.clear() |
|
|
|
faceStrListInVad.clear() |
|
|
|
faceRectListInVad.clear() |
|
|
|
return isSpeak |
|
|
|
} |
|
|
|
|
|
|
|
override fun getCurrentCloseSpeak(closeName: String, isClear: Boolean): Boolean { |
|
|
|
if (!FaceManager.needKSCheck || !hasInitKs) { |
|
|
|
return true |
|
|
|
} |
|
|
|
if (!needFaceCheck) { |
|
|
|
return if (!needFaceAngleCheck) { |
|
|
|
true |
|
|
|
} else { |
|
|
|
val isRightAngle = checkAngle( |
|
|
|
faceListCloseInVad, |
|
|
|
"closeName-$closeName" |
|
|
|
) |
|
|
|
faceListCloseInVad.clear() |
|
|
|
faceStrListCloseInVad.clear() |
|
|
|
faceRectListCloseInVad.clear() |
|
|
|
isRightAngle |
|
|
|
} |
|
|
|
} |
|
|
|
if (faceListCloseInVad.size == 0) { |
|
|
|
Log.e("testface", "size 0 is speak false") |
|
|
|
return false |
|
|
|
} |
|
|
|
if (needFaceAngleCheck) { |
|
|
|
val isAngleOk = checkAngle( |
|
|
|
faceListCloseInVad, |
|
|
|
"closeName-$closeName" |
|
|
|
) |
|
|
|
if (!isAngleOk) { |
|
|
|
faceListCloseInVad.clear() |
|
|
|
faceStrListCloseInVad.clear() |
|
|
|
faceRectListCloseInVad.clear() |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
//needPause = true; |
|
|
|
val start = System.currentTimeMillis() |
|
|
|
//if (FaceManager.faceCount == 1 && faceListInVad.size() < 20) |
|
|
|
run {} |
|
|
|
// while (FaceManager.faceCount != 0) { |
|
|
|
// try { |
|
|
|
// Thread.sleep(20); |
|
|
|
// } catch (InterruptedException e) { |
|
|
|
// throw new RuntimeException(e); |
|
|
|
// } |
|
|
|
// } |
|
|
|
val isSpeak = checkSpeak(closeName, "", faceListCloseInVad) |
|
|
|
if (!isSpeak) { |
|
|
|
} |
|
|
|
faceListCloseInVad.clear() |
|
|
|
faceStrListCloseInVad.clear() |
|
|
|
faceRectListCloseInVad.clear() |
|
|
|
return isSpeak |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun checkAngle( |
|
|
|
faceList: ConcurrentLinkedQueue<FaceLandmarkInfo?>, |
|
|
|
name: String |
|
|
|
): Boolean { |
|
|
|
val count = faceList.size |
|
|
|
var overAngleCount = 0 |
|
|
|
for (face in faceList) { |
|
|
|
if (face == null) { |
|
|
|
overAngleCount++ |
|
|
|
continue |
|
|
|
} |
|
|
|
if (face.yaw > 0.3f || face.yaw < -0.3f) { |
|
|
|
overAngleCount++ |
|
|
|
} else { |
|
|
|
LogUtils.e( |
|
|
|
"testtwoface", |
|
|
|
"face.yaw " + face.yaw + " time " + DuiMessageObserver.mTime + " " + name |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
val rightAngleCount = count - overAngleCount |
|
|
|
LogUtils.e( |
|
|
|
"testtwoface", |
|
|
|
"face.yaw overAngleCount $overAngleCount count $count name $name" |
|
|
|
) |
|
|
|
return if (count <= 12) { |
|
|
|
rightAngleCount * 10 > count |
|
|
|
} else { |
|
|
|
rightAngleCount * 3 > count |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fun checkSpeak( |
|
|
|
name: String, |
|
|
|
logTag: String, |
|
|
|
faceList: ConcurrentLinkedQueue<FaceLandmarkInfo?> |
|
|
|
): Boolean { |
|
|
|
val start = System.currentTimeMillis() |
|
|
|
var isSpeak = false |
|
|
|
var mouthOpen = 0 |
|
|
|
var mouthClose = 0 |
|
|
|
var mouthOther = 0 |
|
|
|
var overAngleCount = 0 |
|
|
|
var faceType = -1f |
|
|
|
var mouthChangeCount = 0 |
|
|
|
val count = faceList.size |
|
|
|
for (face in faceList) { |
|
|
|
if (face == null) { |
|
|
|
continue |
|
|
|
} |
|
|
|
if (faceType >= 0 && (faceType - face.mouseClose) > 0.1f) { |
|
|
|
mouthChangeCount++ |
|
|
|
} |
|
|
|
faceType = face.mouseClose |
|
|
|
if (face.mouseClose < 0.9f) { |
|
|
|
mouthOpen++ |
|
|
|
} else { |
|
|
|
mouthClose++ |
|
|
|
} |
|
|
|
if (face.pitch > 0.3f || face.pitch < -0.3f) { |
|
|
|
overAngleCount++ |
|
|
|
} |
|
|
|
} |
|
|
|
if (faceList.size <= 8) { |
|
|
|
isSpeak = mouthChangeCount > 0 || overAngleCount > 0 |
|
|
|
} else if (overAngleCount > 0) { |
|
|
|
isSpeak = mouthChangeCount > 0 || overAngleCount * 16 >= count |
|
|
|
} else if (mouthOpen > 0 && mouthClose > 0 || mouthOpen > 0 && mouthOther > 0) { |
|
|
|
// || (mouthClose > 0 && mouthOther > 0) |
|
|
|
isSpeak = true |
|
|
|
} |
|
|
|
if (!isSpeak) { |
|
|
|
if (mouthChangeCount * 2 >= count) { |
|
|
|
isSpeak = true |
|
|
|
} else if (mouthOpen == 0 && count <= 20) { |
|
|
|
if (Math.abs(mouthClose - mouthOther) < 3 || mouthChangeCount > mouthClose || mouthChangeCount > mouthOther) { |
|
|
|
isSpeak = true |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
Logger.e("djASR-嘴型检测: " + logTag + name + " is speak " + isSpeak + " mouthOpen " + mouthOpen + " mouthClose " + mouthClose + " mouthOther " + mouthOther + " mouthChangeCount " + mouthChangeCount + " leftFaceSize " + faceCount + " overAngleCount " + overAngleCount + " time " + DuiMessageObserver.mTime) |
|
|
|
Log.e( |
|
|
|
"testface", |
|
|
|
logTag + name + " is speak " + isSpeak + " mouthOpen " + mouthOpen + " mouthClose " + mouthClose + " mouthOther " + mouthOther + " mouthChangeCount " + mouthChangeCount + " leftFaceSize " + faceCount + " overAngleCount " + overAngleCount + " time " + DuiMessageObserver.mTime + " duration " + (System.currentTimeMillis() - start) |
|
|
|
) |
|
|
|
return isSpeak |
|
|
|
} |
|
|
|
|
|
|
|
} |