CameraX的入门学习与整理
目标跟掌握
CameraX出来已经有段时间了,但是在工作中一直也是使用Camera1,但是使用过程中还是感觉到API设计的不灵活跟不便捷,所以入门看看CameraX。在谷歌官网文档也提供了以下的用例,目前也是app端比较常用跟需要掌握的
导入包
dependencies {
// CameraX core library using the camera2 implementation
def camerax_version = "1.3.0-alpha04"
// The following line is optional, as the core library is included indirectly by camera-camera2
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
// If you want to additionally use the CameraX Lifecycle library
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
// If you want to additionally use the CameraX VideoCapture library
implementation "androidx.camera:camera-video:${camerax_version}"
// If you want to additionally use the CameraX View class
implementation "androidx.camera:camera-view:${camerax_version}"
// If you want to additionally add CameraX ML Kit Vision Integration
implementation "androidx.camera:camera-mlkit-vision:${camerax_version}"
// If you want to additionally use the CameraX Extensions library
implementation "androidx.camera:camera-extensions:${camerax_version}"
}
相机的预览
相机的预览接收硬件的画面,其中我们理解成接收surface就行。
比如PreviewView
重点一分辨率的设置
为什么单独拿出来说分辨率设置重要呢?原因有二
1.工作中接触的Android机器是客户高度定制的,曾经有出现通过Camera1获取的分辨率看到很奇怪的
2.曾经试过不设置预览分辨率直接app奔溃的
所以还是单独拿出来做下笔记吧。
目前验证了一下利用setTargetResolution 设置目标的预览分辨率可以随便设置自已想要的分辨率,跟Camera1 ,2还是有点区别的。
比较特殊的地方是设置了预览的分辨率后就不能设置纵横比了,这两者只能设置其中一个。
Preview preview = new Preview.Builder()
// .setTargetAspectRatio(AspectRatio.RATIO_4_3) //设置纵横比
.setTargetResolution(new Size(50,50))
.build();
重点二旋转角度的设置以及分析
设置预览角度的还是跟PreView这个类相关,目前我的理解是跟预览配置相关的都跟这个类相关
仅仅设置了这个后感觉没啥用,预览角度还是没变化的
.setTargetRotation(Surface.ROTATION_270)
重点三 如何在其他控件上显示相机的预览
surfaceView
TextureView
实现模式官方的文档在PreviewView已经实现了在这两个空间的显示,
COMPATIBLE 模式。在此模式下,PreviewView 会使用 TextureView;
具体有什么作用还待探讨,一般默认即可
代码简单整理,到这一步已经实现了相机的预览了。
/**
* 初始化相机
*/
private void initCameraX() {
// 1.获取ProcessCameraProvider(相机进程提供)
// 2.检查可用性请求 CameraProvider
// 3.有要求绑定生命周期的,所以说需要绑定 Lifecycle
cameraProviderListenableFuture = ProcessCameraProvider.getInstance(getApplication());
cameraProviderListenableFuture.addListener(new Runnable() {
@Override
public void run() {
ProcessCameraProvider processCameraProvider = null;
try {
processCameraProvider = cameraProviderListenableFuture.get();
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build();
initViewPreView(processCameraProvider, cameraSelector);
}
}, ContextCompat.getMainExecutor(this));
}
/**
* 初始化预览
*/
private void initViewPreView(ProcessCameraProvider processCameraProvider, CameraSelector cameraSelector) {
Preview preview = new Preview.Builder().build();
Preview.SurfaceProvider surfaceProvider = previewViewCamerax.getSurfaceProvider();
// 绑定生命周期
Camera camera = processCameraProvider.bindToLifecycle(this, cameraSelector, preview);
// 设置缩放
previewViewCamerax.setScaleType(PreviewView.ScaleType.FILL_CENTER);
preview.setSurfaceProvider(surfaceProvider);
}
图片分析
这个一般用在人工智能或者其他方面对照片进行分析,其实也是跟PreView差不多
ImageAnalysis imageAnalysis =
new ImageAnalysis.Builder()
.setTargetResolution(new Size(1280, 720))
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
processCameraProvider.bindToLifecycle(this, cameraSelector, imageCapture,imageAnalysis, preview);
ExecutorService executorService = Executors.newSingleThreadExecutor();
imageAnalysis.setAnalyzer(executorService, new ImageAnalysis.Analyzer() {
@Override
public void analyze(@NonNull ImageProxy image) {
}
});
拍照
拍照相关类跟 ImageCapture相关,用法大致跟PreView差不多,调用 imageCapture.takePicture
ImageCapture imageCapture;
public void takepicture(View view) {
if (imageCapture == null) {
imageCapture = new ImageCapture.Builder()
.setTargetRotation(view.getDisplay().getRotation())
// .setBufferFormat(ImageFormat.YUV_420_888)
.setBufferFormat(ImageFormat.YUV_420_888)
.setTargetRotation(previewViewCamerax.getDisplay().getRotation())
.build();
processCameraProvider.bindToLifecycle(this, cameraSelector, imageCapture, preview);
}
imageCapture.takePicture(ContextCompat.getMainExecutor(this), new ImageCapture.OnImageCapturedCallback() {
@Override
public void onCaptureSuccess(@NonNull ImageProxy image) {
super.onCaptureSuccess(image);
// 拍摄出来的图片
imv_main.setImageBitmap(image.toBitmap());
}
});
}
录像
没啥悬念,跟这个类相关VideoCapture
总结一下
其实几大用法都很类似,封装了一个usecase,
usecase 包含了预览,拍照,图片分析,录像。
我感觉掌握了预览的配置后其他项都很简单了。整理了一下套路
1.需要一个相机提供的进程 因此有了 ProcessCameraProvider
2.检查是否可用,可用的话就取CameraProvider
3.进行UseCase的配置