I'm creating an app that uses Google ML Kit to detect a human face on an image and draw a rectangle around it. The camera preview is provided by the CameraX (androidx.camera
) library. Inspiration was taken from this question. Here is the problematic fragment of a code:
@OptIn(ExperimentalGetImage::class)
private fun startCamera(deviceSize: Pair<Float, Float>) {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also {
it.surfaceProvider = PreviewView(this).surfaceProvider
}
val size = Size(deviceSize.first, deviceSize.second)
val strategy = ResolutionStrategy(deviceSize, 2)
val rs = ResolutionSelector.Builder().setResolutionStrategy(strategy)
val imageAnalysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setResolutionSelector(rs.build())
.build()
imageAnalysis.setAnalyzer(cameraExecutor) { imageProxy ->
val rotationDegrees = imageProxy.imageInfo.rotationDegrees
val mediaImage = imageProxy.image
if (mediaImage != null) {
val inputImage = InputImage.fromMediaImage(mediaImage, rotationDegrees)
detectFaces(inputImage) { faces ->
drawRectangles(faces)
imageProxy.close()
}
} else {
imageProxy.close()
}
}
val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis)
} catch (e: Exception) {
e.printStackTrace()
}
}, ContextCompat.getMainExecutor(this))
}
The only error shown by the IDE (Android Studio Ladybug 2024.2.1 Patch 3) is
"Cannot access 'constructor(): ResolutionStrategy': it is private in 'androidx/camera/core/resolutionselector/ResolutionStrategy'"
This seems very strange to me as there is a public constructor documented on the Android Developer Website and I can also navigate to the same public constructor by clicking Go To > Declaration
. However when I hover over the constructor used by strategy
, the IDE shows the private constructor. Why does it happen and how to fix it?
Edit: I found out that AspectRatioStrategy
, which is very similar to ResolutionStrategy
and can also be passed to the ResolutionSelector
, is usable in my scenario:
val asp = AspectRatioStrategy(AspectRatio.RATIO_DEFAULT, 1) // no error
I hadn't also mentioned what's the deal about the resolution modification - the rectangles around the detected faces' bounding boxes are displayed but not in the correct ratio (printing mediaImage
dimensions yields 640x480).
I found out that this error is actually a problem with IDE or project structure (I'm not really sure). I found out that the ResolutionStrategy constructor is only available in Java Classes, so I can use it like this:
public class CameraUtils {
public static ResolutionStrategy createStrategy(Size deviceSize) {
return new ResolutionStrategy(deviceSize, ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER);
}
public static ResolutionSelector createSelector(Size deviceSize) {
return new ResolutionSelector.Builder().setResolutionStrategy(createStrategy(deviceSize)).build();
}
}
And then call the helper class from my Kotlin code:
val camera = LifecycleCameraController(this)
camera.imageAnalysisBackpressureStrategy = ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
camera.imageAnalysisResolutionSelector = CameraUtils.createSelector(Size(width, height))