[Android][Java] Object Detection With EfficientDet - 2 Camera 사용

παντοκράτωρ·2024년 7월 12일

Android

목록 보기
4/6

Java Class

AnalyzerUtils

CameraUtils에서 불러온 이미지를 모델을 거쳐 Object Detection 수행

CameraUtils

Camera를 구동하고 촬영한 매 프레임 Image파일(ImageProxy)을 AnlayzerUtils로 전송

MainActivity

CameraUtils 호출

ObjectMarker

AnalyzerUtils에서 분석한 Object를 화면 크기에 맞게 변환 및 직사각형 이미지 생성

MainActivity 생성

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Camera
        CameraUtils cameraUtils = new CameraUtils(this);
        cameraUtils.initializeCamera();
    }
}

activity_main.xml 수정

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <androidx.camera.view.PreviewView
        android:id="@+id/viewFinder"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    </androidx.camera.view.PreviewView>

</androidx.constraintlayout.widget.ConstraintLayout>

CameraUtils 생성

CameraUtils.java

참고: Android CameraX

위 사이트에서 4번까지의 코드를 Java로 변환한 내용이다.
startCamera()만 구현하고 startCamera에서 받아온 이미지 데이터를 AnalyzerUtils에 있는 함수로 넘겨주는 코드이다.

AnalyzerUtils는 다음 포스트에서 작성한다.

public class CameraUtils {
    private Activity dstActivity; // mainActivity 
    private AnalyzerUtils analyzerUtils;
    private Object viewBinding;
    private ExecutorService cameraExecutor;


    public CameraUtils(Activity dstActivity) {
        this.dstActivity = dstActivity;
        analyzerUtils = new AnalyzerUtils(dstActivity);

        viewBinding = ActivityMainBinding.inflate(dstActivity.getLayoutInflater());
        dstActivity.setContentView(((ActivityMainBinding) viewBinding).getRoot());

        cameraExecutor = Executors.newSingleThreadExecutor();
    }

    public void initializeCamera() {
        // Request camera permissions
        if (allPermissionsGranted(dstActivity)) {
            startCamera(dstActivity);
        } else {
            ActivityCompat.requestPermissions(
                    dstActivity, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
        }
    }

    private void takePhoto() {
        // TODO: Implement take photo functionality
    }

    private void captureVideo() {
        // TODO: Implement capture video functionality
    }

    private void startCamera(Activity dstActivity) {
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(dstActivity);
        cameraProviderFuture.addListener(new Runnable() {
            @Override
            public void run() {
                try {
                    ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

                    Preview preview = new Preview.Builder().build();
                    preview.setSurfaceProvider(((ActivityMainBinding) viewBinding).viewFinder.getSurfaceProvider());

                    CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;

                    ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                            .build();

                    imageAnalysis.setAnalyzer(cameraExecutor, new ImageAnalysis.Analyzer() {
                        @OptIn(markerClass = ExperimentalGetImage.class)
                        @Override
                        public void analyze(@NonNull ImageProxy image) {
                            analyzerUtils.analyze(image);
                        }
                    });

                    cameraProvider.unbindAll();
                    cameraProvider.bindToLifecycle((LifecycleOwner) dstActivity, cameraSelector, preview, imageAnalysis);

                } catch (ExecutionException | InterruptedException e) {
                    Log.e(TAG, "Error initializing camera provider", e);
                }
            }
        }, ContextCompat.getMainExecutor(dstActivity));
    }

    private boolean allPermissionsGranted(Activity dstActivity) {
        for (String permission : REQUIRED_PERMISSIONS) {
            if (ContextCompat.checkSelfPermission(
                    dstActivity.getBaseContext(), permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    protected void onDestroy() {
        cameraExecutor.shutdown();
    }

    private static final String FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS";
    private static final int REQUEST_CODE_PERMISSIONS = 10;
    private static final String[] REQUIRED_PERMISSIONS =
            Build.VERSION.SDK_INT <= Build.VERSION_CODES.P
                    ? new String[]{
                    Manifest.permission.CAMERA,
                    Manifest.permission.RECORD_AUDIO,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }
                    : new String[]{
                    Manifest.permission.CAMERA,
                    Manifest.permission.RECORD_AUDIO
            };
}

0개의 댓글