
CameraUtils에서 불러온 이미지를 모델을 거쳐 Object Detection 수행
Camera를 구동하고 촬영한 매 프레임 Image파일(ImageProxy)을 AnlayzerUtils로 전송
CameraUtils 호출
AnalyzerUtils에서 분석한 Object를 화면 크기에 맞게 변환 및 직사각형 이미지 생성
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
<?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.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
};
}