Skip to content

Instantly share code, notes, and snippets.

@apkelly
Created January 17, 2019 03:45
Show Gist options
  • Save apkelly/20af5721483f8d2d5d3654d8de5aed25 to your computer and use it in GitHub Desktop.
Save apkelly/20af5721483f8d2d5d3654d8de5aed25 to your computer and use it in GitHub Desktop.
FaceDetector.kt
class FaceDetector(private val callback: DetectorCallback?) : IFrameProcessor {
interface DetectorCallback {
fun onSuccess(frameData: ByteBuffer, results: List<FirebaseVisionFace>, frameMetadata: FrameMetadata)
fun onFailure(exception: Exception)
}
companion object {
private const val TAG = "FaceDetector"
}
private val delegateDetector = FirebaseVision.getInstance()
.getVisionFaceDetector(
FirebaseVisionFaceDetectorOptions.Builder()
.setLandmarkMode(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
.build()
)
// To keep the latest images and its metadata.
@GuardedBy("this")
private var latestImage: ByteBuffer? = null
@GuardedBy("this")
private var latestImageMetaData: FrameMetadata? = null
// To keep the images and metadata in process.
@GuardedBy("this")
private var processingImage: ByteBuffer? = null
@GuardedBy("this")
private var processingMetaData: FrameMetadata? = null
@Synchronized
override fun process(data: ByteBuffer, frameMetadata: FrameMetadata) {
latestImage = data
latestImageMetaData = frameMetadata
if (processingImage == null && processingMetaData == null) {
processLatestImage()
}
}
@Synchronized
private fun processLatestImage() {
processingImage = latestImage
processingMetaData = latestImageMetaData
latestImage = null
latestImageMetaData = null
if (processingImage != null && processingMetaData != null) {
processImage(processingImage!!, processingMetaData!!)
}
}
private fun processImage(data: ByteBuffer, frameMetadata: FrameMetadata) {
val metadata = FirebaseVisionImageMetadata.Builder()
.setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
.setWidth(frameMetadata.width)
.setHeight(frameMetadata.height)
.setRotation(frameMetadata.rotation)
.build()
val image = FirebaseVisionImage.fromByteBuffer(data, metadata)
delegateDetector.detectInImage(image)
.addOnSuccessListener { results ->
callback?.onSuccess(data, results, frameMetadata)
processLatestImage()
}
.addOnFailureListener { e ->
callback?.onFailure(e)
}
}
override fun stop() {
try {
delegateDetector.close()
} catch (e: IOException) {
Log.e(TAG, "Exception thrown while trying to close Face Detector: $e")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment