UVCAndroid,安卓UVC相机通用开发库(支持多预览和多摄像头) 您所在的位置:网站首页 bluetoothdemoapk UVCAndroid,安卓UVC相机通用开发库(支持多预览和多摄像头)

UVCAndroid,安卓UVC相机通用开发库(支持多预览和多摄像头)

2023-08-18 00:38| 来源: 网络整理| 查看: 265

文章目录 简介主要功能如何使用1. 添加依赖到本地工程2. 获取权限3. 初始化UVC业务类,设置UVC摄像头状态回调,设置TextureView或者SurfaceView的Surface监听回调4. 释放UVC业务类(包含取消UVC摄像头状态回调,停止Camera预览,关闭Camera等操作)5. 图片抓拍6. 录制视频7. 改变摄像机预览参数(包括帧格式、宽度、高度、FPS)8. 调整对比度、亮度、色调、饱和度、白平衡等等一些相机控制参数9.旋转摄像头90度、180度、270度,设置摄像头预览镜像10.设置多个预览11.设置多个摄像头(USB2.0受带宽所限,有可能无法同时连接多个摄像头) 其他API下载演示APK参考

简介

UVCAndroid是一款用于安卓UVC相机的通用开发库。

GitHub源码地址:https://github.com/shiyinghan/UVCAndroid

主要功能

主要功能包括: (1) 支持USB Camera设备检测,画面实时预览; (2) 支持抓拍jpg格式图片,可设置图片压缩质量; (3) 支持录制mp4格式视频,可屏蔽音频,可设置视频和音频的录制参数; (4) 支持获取camera支持的分辨率,和分辨率切换; (5) 支持预览自动识别各种相机的分辨率; (6) 支持旋转摄像头90度、180度、270度; (7) 支持调整对比度、亮度、色调、饱和度、白平衡等等一些相机控制参数; (8) 支持多预览和多摄像头; (9) 支持Android5.0+;

如何使用 1. 添加依赖到本地工程

第一步 添加mavenCentral仓库到工程gradle文件 Step 1. Add the mavenCentral repository to your build file Add it in your root build.gradle at the end of repositories:

allprojects { repositories { ... mavenCentral() } }

第二步 添加依赖到app Module的gradle文件

dependencies { implementation 'com.herohan:UVCAndroid:1.0.5' } 2. 获取权限

Request permissions

List needPermissions = new ArrayList(); needPermissions.add(Manifest.permission.CAMERA); needPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);//拍照和录制视频时需要该权限 //needPermissions.add(Manifest.permission.MANAGE_EXTERNAL_STORAGE); //Android 11 使用该权限替代 WRITE_EXTERNAL_STORAGE needPermissions.add(Manifest.permission.RECORD_AUDIO);//录制视频时需要音频时需要该权限 //这里使用XXPermissions开源框架获取权限,你也可以使用系统原生的,或者其他开源框架获取权限 XXPermissions.with(this) .permission(needPermissions) .request((permissions, all) -> { if(!all){ return; } //摄像头业务操作 }); 3. 初始化UVC业务类,设置UVC摄像头状态回调,设置TextureView或者SurfaceView的Surface监听回调

Initialize CameraHelper,set UVC Camera state callback

private ICameraHelper mCameraHelper; private AspectRatioSurfaceView mCameraViewMain; private ICameraHelper.StateCallback mStateListener; //UVC摄像头状态回调 mStateListener = new ICameraHelper.StateCallback() { //插入UVC设备 @Override public void onAttach(UsbDevice device) { //设置为当前设备(如果没有权限,会显示授权对话框) mCameraHelper.selectDevice(device); } //打开UVC设备成功(也就是已经获取到UVC设备的权限) @Override public void onDeviceOpen(UsbDevice device, boolean isFirstOpen) { //打开UVC摄像头 mCameraHelper.openCamera(); } //打开摄像头成功 @Override public void onCameraOpen(UsbDevice device) { //开始预览 mCameraHelper.startPreview(); //获取预览使用的Size(包括帧格式、宽度、高度、FPS) Size size = mCameraHelper.getPreviewSize(); if (size != null) { int width = size.width; int height = size.height; //需要自适应摄像头分辨率的话,设置新的宽高比 mCameraViewMain.setAspectRatio(width, height); } //添加预览Surface mCameraHelper.addSurface(mCameraViewMain.getHolder().getSurface(), false); } //关闭摄像头成功 @Override public void onCameraClose(UsbDevice device) { if (mCameraHelper != null) { //移除预览Surface mCameraHelper.removeSurface(mCameraViewMain.getHolder().getSurface()); } } //关闭UVC设备成功 @Override public void onDeviceClose(UsbDevice device) { } //断开UVC设备 @Override public void onDetach(UsbDevice device) { } //用户没有授予访问UVC设备的权限 @Override public void onCancel(UsbDevice device) { } }; //设置SurfaceView的Surface监听回调 mCameraViewMain.getHolder().addCallback(new SurfaceHolder.Callback() { //创建了新的Surface @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { if (mCameraHelper != null) { //添加预览Surface mCameraHelper.addSurface(holder.getSurface(), false); } } //Surface发生了改变 @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { } //销毁了原来的Surface @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mCameraHelper != null) { //移除预览Surface mCameraHelper.removeSurface(holder.getSurface()); } } }); mCameraHelper = new CameraHelper(); //设置UVC摄像头状态回调 mCameraHelper.setStateCallback(mStateListener); 4. 释放UVC业务类(包含取消UVC摄像头状态回调,停止Camera预览,关闭Camera等操作)

Release CameraHelper(including canceling UVC Camera state callback, stopping Camera preview, etc.)

mCameraHelper.release(); 5. 图片抓拍

Image Capture

//设置视图片抓拍全局参数(非必须,可以不设置,使用默认值) mCameraHelper.setImageCaptureConfig( mCameraHelper.getImageCaptureConfig().setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)); // mCameraHelper.setImageCaptureConfig( // mCameraHelper.getImageCaptureConfig().setJpegCompressionQuality(90)); //设置需要保存图片文件 File file = FileUtils.getCaptureFile(this, Environment.DIRECTORY_DCIM, ".jpg"); ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(file).build(); // ContentValues contentValues = new ContentValues(); // contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "NEW_IMAGE"); // contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg"); // // ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder( // getContentResolver(), // MediaStore.Images.Media.EXTERNAL_CONTENT_URI, // contentValues).build(); // ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(outputStream).build(); //进行图片抓拍 mCameraHelper.takePicture(options, new ImageCapture.OnImageCaptureCallback() { //图片抓拍成功 @Override public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) { Toast.makeText(TakePictureActivity.this, "save \"" + UriHelper.getPath(TakePictureActivity.this, outputFileResults.getSavedUri()) + "\"", Toast.LENGTH_SHORT).show(); } //图片抓拍出现错误 @Override public void onError(int imageCaptureError, @NonNull String message, @Nullable Throwable cause) { Toast.makeText(TakePictureActivity.this, message, Toast.LENGTH_SHORT).show(); } }); 6. 录制视频

Video Capture

//设置视频录制全局参数(非必须,可以不设置,使用默认值) mCameraHelper.setVideoCaptureConfig( mCameraHelper.getVideoCaptureConfig() .setAudioCaptureEnable(true) // true:有音频;false:没有音频(默认为true) .setBitRate((int) (1024 * 1024 * 25 * 0.25)) .setVideoFrameRate(25) .setIFrameInterval(1)); //设置需要保存视频文件 File file = FileUtils.getCaptureFile(this, Environment.DIRECTORY_MOVIES, ".mp4"); VideoCapture.OutputFileOptions options = new VideoCapture.OutputFileOptions.Builder(file).build(); // ContentValues contentValues = new ContentValues(); // contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "NEW_VIDEO"); // contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4"); // // VideoCapture.OutputFileOptions options = new VideoCapture.OutputFileOptions.Builder( // getContentResolver(), // MediaStore.Video.Media.EXTERNAL_CONTENT_URI, // contentValues).build(); //开始录制 mCameraHelper.startRecording(options, new VideoCapture.OnVideoCaptureCallback() { @Override public void onStart() { } //视频录制成功 @Override public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) { Toast.makeText( RecordVideoActivity.this, "save \"" + UriHelper.getPath(RecordVideoActivity.this, outputFileResults.getSavedUri()) + "\"", Toast.LENGTH_SHORT).show(); } //视频录制出现错误 @Override public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) { Toast.makeText(RecordVideoActivity.this, message, Toast.LENGTH_LONG).show(); } }); 7. 改变摄像机预览参数(包括帧格式、宽度、高度、FPS)

Set camera preview parameters (including frame format, width, height, FPS)

//停止相机预览 mCameraHelper.stopPreview(); //设置摄像机预览参数 mCameraHelper.setPreviewSize(size); //开始相机预览 mCameraHelper.startPreview(); //需要自适应摄像头分辨率的话,设置新的宽高比 mCameraViewMain.setAspectRatio(mPreviewWidth, mPreviewHeight); 8. 调整对比度、亮度、色调、饱和度、白平衡等等一些相机控制参数

Adjust contrast, brightness, hue, saturation, white balance, and other camera controls

//获取UVCControl对象,通过该对象调整相机控制参数 UVCControl control = mCameraHelper.getUVCControl(); //根据监听器设置各种相机控制参数 private void setAllControlChangeListener(UVCControl controls) { // Brightness isbBrightness.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setBrightness(seekParams.progress)); // Contrast isbContrast.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setContrast(seekParams.progress)); // Contrast Auto cbContrastAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setContrastAuto(isChecked); }); // Hue isbHue.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setHue(seekParams.progress)); // Hue Auto cbHueAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setHueAuto(isChecked); }); // Saturation isbSaturation.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setSaturation(seekParams.progress)); // Sharpness isbSharpness.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setSharpness(seekParams.progress)); // Gamma isbGamma.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setGamma(seekParams.progress)); // White Balance isbWhiteBalance.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setWhiteBalance(seekParams.progress)); // White Balance Auto cbWhiteBalanceAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setWhiteBalanceAuto(isChecked); }); // Backlight Compensation isbBacklightComp.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setBacklightComp(seekParams.progress)); // Gain isbGain.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setGain(seekParams.progress)); // Exposure Time isbExposureTime.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setExposureTimeAbsolute(seekParams.progress)); // Exposure Time Auto cbExposureTimeAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setExposureTimeAuto(isChecked); }); // Iris isbIris.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setIrisAbsolute(seekParams.progress)); // Focus isbFocus.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setFocusAbsolute(seekParams.progress)); // Focus Auto cbFocusAuto.setOnCheckedChangeListener((buttonView, isChecked) -> { controls.setFocusAuto(isChecked); }); // Zoom isbZoom.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setZoomAbsolute(seekParams.progress)); // Pan isbPan.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setPanAbsolute(seekParams.progress)); // Tilt isbTilt.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setTiltAbsolute(seekParams.progress)); // Roll isbRoll.setOnSeekChangeListener( (MyOnSeekChangeListener) seekParams -> controls.setRollAbsolute(seekParams.progress)); // Power Line Frequency rgPowerLineFrequency.setOnCheckedChangeListener((group, checkedId) -> { int value = 0; if (checkedId == R.id.rbPowerLineFrequencyDisable) { value = 0; } else if (checkedId == R.id.rbPowerLineFrequency50Hz) { value = 1; } else if (checkedId == R.id.rbPowerLineFrequency60Hz) { value = 2; } else if (checkedId == R.id.rbPowerLineFrequencyAuto) { value = 3; } controls.setPowerlineFrequency(value); }); } // 重置所有相机控制参数为初试值 private void resetAllControlParams(UVCControl control) { // Brightness control.resetBrightness(); // Contrast control.resetContrast(); // Contrast Auto control.resetContrastAuto(); // Hue control.resetHue(); // Hue Auto control.resetHueAuto(); // Saturation control.resetSaturation(); // Sharpness control.resetSharpness(); // Gamma control.resetGamma(); // White Balance control.resetWhiteBalance(); // White Balance Auto control.resetWhiteBalanceAuto(); // Backlight Compensation control.resetBacklightComp(); // Gain control.resetGain(); // Exposure Time control.resetExposureTimeAbsolute(); // Auto-Exposure Mode control.resetAutoExposureMode(); // Iris control.resetIrisAbsolute(); // Focus control.resetFocusAbsolute(); // Focus Auto control.resetFocusAuto(); // Zoom control.resetZoomAbsolute(); // Pan control.resetPanAbsolute(); // Tilt control.resetTiltAbsolute(); // Roll control.resetRollAbsolute(); // Power Line Frequency control.resetPowerlineFrequency(); } 9.旋转摄像头90度、180度、270度,设置摄像头预览镜像

Rotate the camera 90 degrees, 180 degrees, and 270 degrees , set the camera preview mirror

//旋转摄像头 private void rotateBy(int angle) { mPreviewRotation += angle; mPreviewRotation %= 360; if (mPreviewRotation mCameraHelper.setPreviewConfig( mCameraHelper.getPreviewConfig().setRotation(mPreviewRotation)); } } //设置水平镜像显示 private void flipHorizontally() { if (mCameraHelper != null) { mCameraHelper.setPreviewConfig( mCameraHelper.getPreviewConfig().setMirror(MirrorMode.MIRROR_HORIZONTAL)); } } //设置垂直镜像显示 private void flipVertically() { if (mCameraHelper != null) { mCameraHelper.setPreviewConfig( mCameraHelper.getPreviewConfig().setMirror(MirrorMode.MIRROR_VERTICAL)); } } 10.设置多个预览

Set multiple previews

mCameraHelper.addSurface(svCameraViewMain.getHolder().getSurface(), false); mCameraHelper.addSurface(svCameraViewSecond.getHolder().getSurface(), false); mCameraHelper.addSurface(svCameraViewThird.getHolder().getSurface(), false); mCameraHelper.addSurface(svCameraViewFourth.getHolder().getSurface(), false); 11.设置多个摄像头(USB2.0受带宽所限,有可能无法同时连接多个摄像头)

Setting multiple Cameras

private ICameraHelper mCameraHelperLeft; private ICameraHelper mCameraHelperRight; private AspectRatioSurfaceView svCameraViewLeft; private AspectRatioSurfaceView svCameraViewRight; private UsbDevice mUsbDeviceLeft; private UsbDevice mUsbDeviceRight; private final ICameraHelper.StateCallback mStateListenerLeft = new ICameraHelper.StateCallback() { @Override public void onAttach(UsbDevice device) { synchronized (mSync) { if (mUsbDeviceLeft == null && !device.equals(mUsbDeviceRight)) { selectDeviceLeft(device); } } } @Override public void onDeviceOpen(UsbDevice device, boolean isFirstOpen) { if (device.equals(mUsbDeviceLeft)) { UVCParam param = new UVCParam(); param.setQuirks(UVCCamera.UVC_QUIRK_FIX_BANDWIDTH); mCameraHelperLeft.openCamera(param); } } @Override public void onCameraOpen(UsbDevice device) { if (device.equals(mUsbDeviceLeft)) { mCameraHelperLeft.startPreview(); Size size = mCameraHelperLeft.getPreviewSize(); if (size != null) { int width = size.width; int height = size.height; //auto aspect ratio svCameraViewLeft.setAspectRatio(width, height); } mCameraHelperLeft.addSurface(svCameraViewLeft.getHolder().getSurface(), false); mIsCameraLeftConnected = true; } } @Override public void onCameraClose(UsbDevice device) { if (device.equals(mUsbDeviceLeft)) { if (mCameraHelperLeft != null) { mCameraHelperLeft.removeSurface(svCameraViewLeft.getHolder().getSurface()); } mIsCameraLeftConnected = false; } } @Override public void onDeviceClose(UsbDevice device) { } @Override public void onDetach(UsbDevice device) { if (device.equals(mUsbDeviceLeft)) { mUsbDeviceLeft = null; } } @Override public void onCancel(UsbDevice device) { if (device.equals(mUsbDeviceLeft)) { mUsbDeviceLeft = null; } } }; private final ICameraHelper.StateCallback mStateListenerRight = new ICameraHelper.StateCallback() { @Override public void onAttach(UsbDevice device) { synchronized (mSync) { if (mUsbDeviceRight == null && !device.equals(mUsbDeviceLeft)) { selectDeviceRight(device); } } } @Override public void onDeviceOpen(UsbDevice device, boolean isFirstOpen) { if (device.equals(mUsbDeviceRight)) { UVCParam param = new UVCParam(); param.setQuirks(UVCCamera.UVC_QUIRK_FIX_BANDWIDTH); mCameraHelperRight.openCamera(param); } } @Override public void onCameraOpen(UsbDevice device) { if (device.equals(mUsbDeviceRight)) { mCameraHelperRight.startPreview(); Size size = mCameraHelperRight.getPreviewSize(); if (size != null) { int width = size.width; int height = size.height; //auto aspect ratio svCameraViewRight.setAspectRatio(width, height); } mCameraHelperRight.addSurface(svCameraViewRight.getHolder().getSurface(), false); mIsCameraRightConnected = true; } } @Override public void onCameraClose(UsbDevice device) { if (device.equals(mUsbDeviceRight)) { if (mCameraHelperRight != null) { mCameraHelperRight.removeSurface(svCameraViewRight.getHolder().getSurface()); } mIsCameraRightConnected = false; } } @Override public void onDeviceClose(UsbDevice device) { } @Override public void onDetach(UsbDevice device) { if (device.equals(mUsbDeviceRight)) { mUsbDeviceRight = null; } } @Override public void onCancel(UsbDevice device) { if (device.equals(mUsbDeviceRight)) { mUsbDeviceRight = null; } } }; svCameraViewLeft.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { if (mCameraHelperLeft != null) { mCameraHelperLeft.addSurface(holder.getSurface(), false); } } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mCameraHelperLeft != null) { mCameraHelperLeft.removeSurface(holder.getSurface()); } } }); svCameraViewRight.setAspectRatio(DEFAULT_WIDTH, DEFAULT_HEIGHT); svCameraViewRight.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { if (mCameraHelperRight != null) { mCameraHelperRight.addSurface(holder.getSurface(), false); } } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { if (mCameraHelperRight != null) { mCameraHelperRight.removeSurface(holder.getSurface()); } } }); mCameraHelperLeft = new CameraHelper(); mCameraHelperLeft.setStateCallback(mStateListenerLeft); mCameraHelperRight = new CameraHelper(); mCameraHelperRight.setStateCallback(mStateListenerRight); 其他API 方法说明getDeviceList()获取当前检测到的所有UVC设备getSupportedFormatList()获取当前摄像头支持的Format列表getSupportedSizeList()获取当前摄像头支持的Size列表getPreviewSize()获取当前摄像头正在使用的预览SizesetButtonCallback()设置按钮事件回调setFrameCallback()设置实时预览图像数据回调(请在StateCallback的onDeviceOpen或者onCameraOpen回调函数里面调用,使用方法可以参考demo里面的SetFrameCallbackActivity),支持格式 UVCCamera.PIXEL_FORMAT_YUV;PIXEL_FORMAT_NV12;PIXEL_FORMAT_NV21;PIXEL_FORMAT_RGB565;PIXEL_FORMAT_RGBX等格式openCamera(Size size)用指定格式打开当前摄像头closeCamera()关闭当前摄像头isRecording()是否正在录像isCameraOpened()是否已经打开当前摄像头 下载演示APK

Download demo APK 在这里插入图片描述 app-debug.apk

在这里插入图片描述 demo-debug.apk

参考

saki4510t/UVCCamera



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有