package com.yeyupiaoling.teststadiometry; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.Manifest; import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.ImageFormat; import android.graphics.Matrix; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.ImageReader; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import android.util.Size; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import org.opencv.android.OpenCVLoader; import java.util.Arrays; import java.util.List; public class CameraActivity extends AppCompatActivity { private static final String TAG = CameraActivity.class.getSimpleName(); private CameraCaptureSession mCaptureSession; private CameraDevice mCameraDevice; private HandlerThread mCaptureThread; private Handler mCaptureHandler; private ImageReader mImageReader; private boolean isFont = false; private Size mPreviewSize; private boolean mCapturing; private AutoFitTextureView mTextureView; private ImageView imageViewLeft; private ImageView imageViewRight; private ImageView imageViewResult; private int sensorOrientation = 0; private View bgView; private LinearLayout ll; private TextView textView; private StereoBMUtil stereoBMUtil; private Bitmap leftBitmap; private Bitmap rightBitmap; @SuppressLint("ClickableViewAccessibility") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); // 权限申请 if (!hasPermission()) { requestPermission(); } //初始化 if (OpenCVLoader.initDebug()) { Log.d(TAG, "OpenCVLoader初始化成功"); } stereoBMUtil = new StereoBMUtil(); mTextureView = findViewById(R.id.texture_view); imageViewLeft = findViewById(R.id.imageViewLeft); imageViewRight = findViewById(R.id.imageViewRight); imageViewResult = findViewById(R.id.imageViewResult); bgView = findViewById(R.id.bg_view); ll = findViewById(R.id.show_ll); textView = findViewById(R.id.result_tv); Button button2 = findViewById(R.id.button2); Button button3 = findViewById(R.id.button3); Button button4 = findViewById(R.id.button4); // 拍照获取左右摄像头的图像 button2.setOnClickListener(v -> { bgView.setVisibility(View.VISIBLE); ll.setVisibility(View.VISIBLE); Bitmap imgBitmap = mTextureView.getBitmap(); Bitmap b = Utils.rotateBitmap(imgBitmap, 360 - sensorOrientation); List bitmapList = Utils.bisectionBitmap(b); // 左右目摄像头的图像 leftBitmap = bitmapList.get(0); rightBitmap = bitmapList.get(1); imageViewLeft.setImageBitmap(leftBitmap); imageViewRight.setImageBitmap(rightBitmap); }); // 显示相机预览 button3.setOnClickListener(v -> { bgView.setVisibility(View.GONE); ll.setVisibility(View.GONE); }); // 执行StereoBM算法 button4.setOnClickListener(v -> { Bitmap result = stereoBMUtil.compute(leftBitmap, rightBitmap); imageViewResult.setImageBitmap(result); }); // 点击计算后的图片,获取三维坐标数据 imageViewResult.setOnTouchListener((v, event) -> { // 获取触摸点的坐标 x, y float x = event.getX(); float y = event.getY(); float[] dst = new float[2]; Matrix imageMatrix = imageViewResult.getImageMatrix(); Matrix inverseMatrix = new Matrix(); imageMatrix.invert(inverseMatrix); inverseMatrix.mapPoints(dst, new float[]{x, y}); int dstX = (int) dst[0]; int dstY = (int) dst[1]; // 获取该点的三维坐标 double[] c = stereoBMUtil.getCoordinate(dstX, dstY); String s = String.format("点(%d, %d) 三维坐标:[%.2f, %.2f, %.2f]", dstX, dstY, c[0], c[1], c[2]); Log.d(TAG, s); textView.setText(s); return true; }); } // 初始化以下变量和状态 private void initStatus() { // 启动线程 startCaptureThread(); // 判断SurfaceTexture是否可用,可用就直接启动捕获图片 if (mTextureView.isAvailable()) { startCapture(); } else { mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { startCapture(); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { } }); } } // 启动捕获图片 private void startCapture() { // 判断是否正处于捕获图片的状态 if (mCapturing) return; mCapturing = true; final CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); String cameraIdAvailable = null; try { assert manager != null; for (final String cameraId : manager.getCameraIdList()) { final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); // 设置相机前摄像头或者后摄像头 if (isFont) { if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) { cameraIdAvailable = cameraId; break; } } else { if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) { cameraIdAvailable = cameraId; break; } } } } catch (CameraAccessException e) { Log.e(TAG, "启动图片捕获异常 ", e); } try { assert cameraIdAvailable != null; final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIdAvailable); final StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); try { sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); Log.i(TAG, "orientation: " + sensorOrientation); } catch (Exception e) { e.printStackTrace(); } assert map != null; mPreviewSize = Utils.chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), mTextureView.getWidth(), mTextureView.getHeight()); Log.d("mPreviewSize", String.valueOf(mPreviewSize)); mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth()); manager.openCamera(cameraIdAvailable, new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice camera) { mCameraDevice = camera; createCaptureSession(); } @Override public void onDisconnected(@NonNull CameraDevice camera) { camera.close(); mCameraDevice = null; mCapturing = false; } @Override public void onError(@NonNull CameraDevice camera, final int error) { Log.e(TAG, "打开相机错误 = " + error); camera.close(); mCameraDevice = null; mCapturing = false; } }, mCaptureHandler); } catch (CameraAccessException | SecurityException e) { mCapturing = false; Log.e(TAG, "启动图片捕获异常 ", e); } } // 创建捕获图片session private void createCaptureSession() { try { final SurfaceTexture texture = mTextureView.getSurfaceTexture(); texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); final Surface surface = new Surface(texture); final CaptureRequest.Builder captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); captureRequestBuilder.addTarget(surface); mImageReader = ImageReader.newInstance( mPreviewSize.getWidth(), mPreviewSize.getHeight(), ImageFormat.JPEG, 10); mCameraDevice.createCaptureSession( Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { if (null == mCameraDevice) { return; } mCaptureSession = cameraCaptureSession; try { captureRequestBuilder.set( CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); captureRequestBuilder.set( CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); CaptureRequest previewRequest = captureRequestBuilder.build(); mCaptureSession.setRepeatingRequest( previewRequest, new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) { super.onCaptureProgressed(session, request, partialResult); } @Override public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) { super.onCaptureFailed(session, request, failure); Log.d(TAG, "onCaptureFailed = " + failure.getReason()); } @Override public void onCaptureSequenceCompleted(@NonNull CameraCaptureSession session, int sequenceId, long frameNumber) { super.onCaptureSequenceCompleted(session, sequenceId, frameNumber); Log.d(TAG, "onCaptureSequenceCompleted"); } }, mCaptureHandler); } catch (final CameraAccessException e) { Log.e(TAG, "onConfigured exception ", e); } } @Override public void onConfigureFailed(@NonNull final CameraCaptureSession cameraCaptureSession) { Log.e(TAG, "onConfigureFailed "); } }, null); } catch (final CameraAccessException e) { Log.e(TAG, "创建捕获图片session异常 ", e); } } // 关闭相机 private void closeCamera() { if (mCaptureSession != null) { mCaptureSession.close(); mCaptureSession = null; } if (mCameraDevice != null) { mCameraDevice.close(); mCameraDevice = null; } if (mImageReader != null) { mImageReader.close(); mImageReader = null; } mCapturing = false; } // 关闭捕获图片线程 private void stopCaptureThread() { try { if (mCaptureThread != null) { mCaptureThread.quitSafely(); mCaptureThread.join(); } mCaptureThread = null; mCaptureHandler = null; } catch (final Exception e) { e.printStackTrace(); } } @Override protected void onPause() { // 关闭相机 closeCamera(); stopCaptureThread(); super.onPause(); } @Override protected void onStop() { // 关闭相机 closeCamera(); stopCaptureThread(); super.onStop(); } // 启动捕获图片线程 private void startCaptureThread() { mCaptureThread = new HandlerThread("capture"); mCaptureThread.start(); mCaptureHandler = new Handler(mCaptureThread.getLooper()); } @Override protected void onResume() { initStatus(); super.onResume(); } // check had permission private boolean hasPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; } else { return true; } } // request permission private void requestPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { requestPermissions(new String[]{Manifest.permission.CAMERA}, 1); } } }