package com.example.fragment; 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 androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.fragment.app.Fragment; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import android.util.Size; import android.view.LayoutInflater; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.example.smartglasses.R; import com.example.otherclass.AutoFitTextureView; import com.example.otherclass.StereoBMUtil; import com.example.otherclass.Utils; import com.example.otherclass.AutoFitTextureView; import org.opencv.android.OpenCVLoader; import java.util.Arrays; import java.util.List; @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public class CameraFragment extends Fragment { 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; public CameraFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @SuppressLint("ClickableViewAccessibility") @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view=inflater.inflate(R.layout.fragment_camera, container, false); // 权限申请 if (!hasPermission()) { requestPermission(); } //初始化 if (OpenCVLoader.initDebug()) { Log.d("Test", "OpenCVLoader初始化成功"); } stereoBMUtil = new StereoBMUtil(); mTextureView = view.findViewById(R.id.texture_view); imageViewLeft = view.findViewById(R.id.imageViewLeft); imageViewRight = view.findViewById(R.id.imageViewRight); imageViewResult = view.findViewById(R.id.imageViewResult); bgView = view.findViewById(R.id.bg_view); ll = view.findViewById(R.id.show_ll); textView = view.findViewById(R.id.result_tv); Button button2 = view.findViewById(R.id.button2); Button button3 = view.findViewById(R.id.button3); Button button4 = view.findViewById(R.id.button4); // 拍照获取左右摄像头的图像 button2.setOnClickListener(v -> { Log.d("Test", "点击打开摄像头 "); bgView.setVisibility(View.VISIBLE); ll.setVisibility(View.VISIBLE); Bitmap imgBitmap = mTextureView.getBitmap(); Log.d("Test", "getBitmap()v "); Bitmap b = Utils.rotateBitmap(imgBitmap, 360 - sensorOrientation); Log.d("Test", " rotateBitmap"); List bitmapList = Utils.bisectionBitmap(b); // 左右目摄像头的图像 leftBitmap = bitmapList.get(0); rightBitmap = bitmapList.get(1); Log.d("Test", "getbitmap成功 "); 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; }); return view; } // 初始化以下变量和状态 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) { } }); } } // 启动捕获图片 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void startCapture() { // 判断是否正处于捕获图片的状态 if (mCapturing) return; mCapturing = true; // final CameraManager manager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE); final CameraManager manager = (CameraManager) getActivity().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 public void onPause() { // 关闭相机 closeCamera(); stopCaptureThread(); super.onPause(); } @Override public void onStop() { // 关闭相机 closeCamera(); stopCaptureThread(); super.onStop(); } // 启动捕获图片线程 private void startCaptureThread() { mCaptureThread = new HandlerThread("capture"); mCaptureThread.start(); mCaptureHandler = new Handler(mCaptureThread.getLooper()); } @Override public void onResume() { initStatus(); super.onResume(); } // check had permission private boolean hasPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return getActivity().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); } } }