android Camera2 API适配百度人脸识别SDK
Camera2 API替換Camera API之后的問題
camera和camera2的最主要區別之一就是camera2不再支持nv21的輸出,通常我們為了使視頻預覽更加的流暢,會采用YUV_420_888的輸出格式,以下是一段camera2的設置代碼片段
...mImageReader = ImageReader.newInstance(width, height, ImageFormat.YUV_420_888, 2)mImageReader?.setOnImageAvailableListener(imageAvailableListener, null)mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)mCameraDevice.createCaptureSession(listOf(mPreviewSurface, mImageReader.surface),object : CameraCaptureSession.StateCallback() {override fun onConfigured(session: CameraCaptureSession) {mCaptureSession = session// 設置完后自動開始預覽// 設置預覽輸出的 SurfacemPreviewRequestBuilder.addTarget(mPreviewSurface) mPreviewRequestBuilder.addTarget(mImageReader.surface)mPreviewRequest = mPreviewRequestBuilder.build()mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mBackgroundHandler)}override fun onConfigureFailed(session: CameraCaptureSession) {Log.e(TAG, "ConfigureFailed. session: mCaptureSession")}}, mBackgroundHandler) // handle 傳入 null 表示使用當前線程的 Looper ... ...private val imageAvailableListener = ImageReader.OnImageAvailableListener {val image = it.acquireLatestImage()val data = image.getNV21DataFromYUV420888Image()val imageWidth = image.widthval imageHeight = image.heightimage.close()// 攝像頭預覽數據進行人臉檢測,使用rgb活體檢測FaceSDKManager.getInstance().onDetectCheck(data, null, null,imageHeight, imageWidth, 1, mFaceDetectCallBack)} ...百度人臉識別SDK接受的圖片格式類型
百度人臉識別SDK則使用的仍是NV21格式的圖片數據輸出,因此我們需要在mImageAvailableListener獲得image數據的時候,將YUV_420_888的圖片數據流轉換為NV_21
YUV_420_888 轉換NV_21
先來看一下android中對于YUV_420_888是如何定義的
/*** <p>Multi-plane Android YUV 420 format</p>** <p>This format is a generic YCbCr format, capable of describing any 4:2:0* chroma-subsampled planar or semiplanar buffer (but not fully interleaved),* with 8 bits per color sample.</p>** <p>Images in this format are always represented by three separate buffers* of data, one for each color plane. Additional information always* accompanies the buffers, describing the row stride and the pixel stride* for each plane.</p>** <p>The order of planes in the array returned by* {@link android.media.Image#getPlanes() Image#getPlanes()} is guaranteed such that* plane #0 is always Y, plane #1 is always U (Cb), and plane #2 is always V (Cr).</p>** <p>The Y-plane is guaranteed not to be interleaved with the U/V planes* (in particular, pixel stride is always 1 in* {@link android.media.Image.Plane#getPixelStride() yPlane.getPixelStride()}).</p>** <p>The U/V planes are guaranteed to have the same row stride and pixel stride* (in particular,* {@link android.media.Image.Plane#getRowStride() uPlane.getRowStride()}* == {@link android.media.Image.Plane#getRowStride() vPlane.getRowStride()} and* {@link android.media.Image.Plane#getPixelStride() uPlane.getPixelStride()}* == {@link android.media.Image.Plane#getPixelStride() vPlane.getPixelStride()};* ).</p>** <p>For example, the {@link android.media.Image} object can provide data* in this format from a {@link android.hardware.camera2.CameraDevice}* through a {@link android.media.ImageReader} object.</p>** @see android.media.Image* @see android.media.ImageReader* @see android.hardware.camera2.CameraDevice*/public static final int YUV_420_888 = 0x23;由此可見:
參考這篇文章對于YUV_420_888數據內容的分析,image.planes[1]和image.planes[2]都為UV數據的交錯存儲,只是順序錯開一位
image.planes[1]為UVUVUVUVUVUVUVUV,而image.planes[2]為VUVUVUVUVUVUVUVU
而NV21格式的編碼結構如下圖所示,是Y plane + VU plane:
可見NV21格式即為image.planes[0]+image.planes[2]
(同理NV12格式為image.planes[0]+image.planes[1])
因此我們可以得到從YUV_420_888中提取出NV21編碼格式圖片數據的方法為:
fun Image.getNV21DataFromYUV420888Image(): ByteArray? {return if (format == ImageFormat.YUV_420_888) {//plane[0] + plane[2] =NV21//plane[0] + plane[1] =NV12val data = ByteArray(planes[0].buffer.capacity() * 3 / 2)val buff0Offset: Int = planes[0].buffer.capacity()planes[0].buffer.get(data, 0, buff0Offset)planes[2].buffer.get(data, buff0Offset, planes[2].buffer.capacity())data} else {null} }由于這里的數據提取并沒有對數據進行轉換操作和計算,僅僅是把兩個plane的數據直接提取到byteArray中,因此并不需要使用cpp代碼來提升轉換效率,java/kotlin代碼也足夠了。
參考文章:
Camera2 YUV420_888
NV21與I420
總結
以上是生活随笔為你收集整理的android Camera2 API适配百度人脸识别SDK的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux环境用opencv读取图片,基
- 下一篇: 梳理百年深度学习发展史-七月在线机器学习