[英]How to increase Camera Speed in Android with CameraX
Hi I am new to Android Programming.嗨,我是 Android 编程的新手。
As the title, How to increase speed of take picture with CameraX or Camera2 or OpenCV?如标题,如何提高 CameraX 或 Camera2 或 OpenCV 的拍照速度? My project goal is image processing(4k image) with Android and OpenCV as fast as possible.
我的项目目标是尽可能快地使用 Android 和 OpenCV 进行图像处理(4k 图像)。
If you have any comments, please let me know.如果您有任何意见,请告诉我。
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) {
Preview preview = new Preview.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
.build();
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
executor = Executors.newSingleThreadExecutor();
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
ImageCapture imageCapture = new ImageCapture.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.build();
camera_capture_button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Log.v("Info", "Button Click");
imageCapture.takePicture(executor , new ImageCapture.OnImageCapturedCallback() {
@Override
public void onCaptureSuccess(@NonNull ImageProxy image) {
super.onCaptureSuccess(image);
Log.v("Info", "Capture Success = W:" + image.getWidth() + "/" + "H:" + image.getHeight());
Bitmap bitmap = toBitmap(image);
Log.v("Info", "Bitmat cvt = W:" + bitmap.getWidth() + "/" + "H:" + bitmap.getHeight());
Mat matOriginal = new Mat();
Mat matResult = new Mat();
Utils.bitmapToMat(bitmap, matOriginal);
Log.v("Info", "Mat cvt = W:" + matOriginal.width() + "/" + "H:" + matOriginal.height());
Imgproc.cvtColor(matOriginal, matResult, Imgproc.COLOR_BGR2HSV);
image.close();
}
@Override
public void onError(@NonNull ImageCaptureException exception) {
Log.v("Info", "Capture Error");
exception.printStackTrace();
}
});
}
});
Here is Logcat Message to measure Time这是用于测量时间的 Logcat 消息
2021-05-12 16:20:40.427 V/Info: Button Click 2021-05-12 16:20:40.427 V/Info: 按钮点击
2021-05-12 16:20:40.976 V/Info: Capture Success = W:3840/H:2160 2021-05-12 16:20:40.976 V/信息:捕获成功 = W:3840/H:2160
2021-05-12 16:20:41.092 V/Info: Bitmap cvt = W:3840/H:2160 2021-05-12 16:20:41.092 V/信息:Bitmap cvt = W:3840/H:2160
2021-05-12 16:20:41.106 V/Info: Mat cvt = W:3840/H:2160 2021-05-12 16:20:41.106 V/信息:Mat cvt = W:3840/H:2160
as the Result作为结果
549msec - takePicture (too Slow, I think) 549msec - takePicture(我觉得太慢了)
116msec - Bitmap Conversion 116 毫秒 - Bitmap 转换
014msec - Mat Conversion 014msec - 垫转换
if you don't want resolution image is high.如果您不希望分辨率图像很高。 you can use image analysis for high speed capture https://developer.android.com/training/camerax/analyze
您可以使用图像分析进行高速捕获https://developer.android.com/training/camerax/analyze
You can try to convert the image to Mat without converting first to bitmap, Use this extension function:您可以尝试将图像转换为 Mat 而无需先转换为 bitmap,使用此扩展名 function:
fun Image.yuvToRgba(): Mat {
val rgbaMat = Mat()
if (format == ImageFormat.YUV_420_888
&& planes.size == 3) {
val chromaPixelStride = planes[1].pixelStride
if (chromaPixelStride == 2) { // Chroma channels are interleaved
assert(planes[0].pixelStride == 1)
assert(planes[2].pixelStride == 2)
val yPlane = planes[0].buffer
val uvPlane1 = planes[1].buffer
val uvPlane2 = planes[2].buffer
val yMat = Mat(height, width, CvType.CV_8UC1, yPlane)
val uvMat1 = Mat(height / 2, width / 2, CvType.CV_8UC2, uvPlane1)
val uvMat2 = Mat(height / 2, width / 2, CvType.CV_8UC2, uvPlane2)
val addrDiff = uvMat2.dataAddr() - uvMat1.dataAddr()
if (addrDiff > 0) {
assert(addrDiff == 1L)
Imgproc.cvtColorTwoPlane(yMat, uvMat1, rgbaMat, Imgproc.COLOR_YUV2BGR_NV12)
} else {
assert(addrDiff == -1L)
Imgproc.cvtColorTwoPlane(yMat, uvMat2, rgbaMat, Imgproc.COLOR_YUV2BGR_NV21)
}
} else { // Chroma channels are not interleaved
val yuvBytes = ByteArray(width * (height + height / 2))
val yPlane = planes[0].buffer
val uPlane = planes[1].buffer
val vPlane = planes[2].buffer
yPlane.get(yuvBytes, 0, width * height)
val chromaRowStride = planes[1].rowStride
val chromaRowPadding = chromaRowStride - width / 2
var offset = width * height
if (chromaRowPadding == 0) {
// When the row stride of the chroma channels equals their width, we can copy
// the entire channels in one go
uPlane.get(yuvBytes, offset, width * height / 4)
offset += width * height / 4
vPlane.get(yuvBytes, offset, width * height / 4)
} else {
// When not equal, we need to copy the channels row by row
for (i in 0 until height / 2) {
uPlane.get(yuvBytes, offset, width / 2)
offset += width / 2
if (i < height / 2 - 1) {
uPlane.position(uPlane.position() + chromaRowPadding)
}
}
for (i in 0 until height / 2) {
vPlane.get(yuvBytes, offset, width / 2)
offset += width / 2
if (i < height / 2 - 1) {
vPlane.position(vPlane.position() + chromaRowPadding)
}
}
}
val yuvMat = Mat(height + height / 2, width, CvType.CV_8UC1)
yuvMat.put(0, 0, yuvBytes)
Imgproc.cvtColor(yuvMat, rgbaMat, Imgproc.COLOR_YUV2BGR_I420, 4)
}
}
return rgbaMat
}
And call it this way:并这样称呼它:
image.image?.let {
if (it.format == ImageFormat.YUV_420_888
&& it.planes.size == 3
) {
val rgbaMat = it.yuvToRgba()
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.