I've got a simple setup:
preview = new Preview.Builder().build();
preview.setSurfaceProvider(mPreviewView.createSurfaceProvider());
imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(new Size(mPreviewView.getWidth(),mPreviewView.getHeight())).build();
imageAnalysis.setAnalyzer(executor, new PaperImageAnalyser());
ImageAnalyzer:
@SuppressLint("UnsafeExperimentalUsageError")
@Override
public void analyze(@NonNull ImageProxy imageProxy) {
    Image mediaImage = imageProxy.getImage();
    if (mediaImage != null) {
        InputImage image = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());
        Log.e("madieaimage",mediaImage.getHeight() + " and with" + mediaImage.getWidth()); //480 and with640
        Log.e("inputimage", image.getHeight() + " and width" + image.getWidth()); //480 and width640
        Log.e("imageproxy", image.getHeight() + " and width" + image.getWidth()); //480 and width640
        Log.e("cameraimp previewview ", CameraImp.mPreviewView.getBitmap().getHeight() + " and widht" +  CameraImp.mPreviewView.getBitmap().getWidth()); //2145 and widht1080
        image =  InputImage.fromBitmap(CameraImp.mPreviewView.getBitmap(),0); //analyzes much better cause resolution is set but its not good practise right?
    }
    
    //analyze with image...
}
The issue is that the resolution of the Image I receive from the analyze method is much smaller than the previewview resoltion (widht/height), so that causes that images are not really good recongnized.
If I use the bitmap of the previewview I get the entire pic of the screen basically which works better for the analyzation, but thats bad practice I assume?
So my question is: Is it possible to set the resolution of the ImageAnalyzer (eg setTargetResolution) I tried above?
Or what would the best way be to deal with such an issue?
If I use the bitmap of the previewview I get the entire pic of the screen basically which works better for the analyzation, but thats bad practice I assume?
Yes this is bad practice performance-wise because buffer copy is very expensive.
So my question is: Is it possible to set the resolution of the ImageAnalyzer (eg setTargetResolution) I tried above?
It's possible on some of the devices if you e.g. set both resolution to 1080p. However there is no guarantee it will work everywhere because it might not be supported by the camera hardware. Also, depending on your usage scenario, a high resolution image analysis could also be a bad practice because analysis usually do not require such a high resolution.
May I ask why do you need the resolution of Preview and ImageAnalysis to be the same?
I just faced the same problem, I'd like to use higher resolution for PreviewView and ImageCapture, and smaller resolution for ImageAnalysis, but i want them to looks same in both aspect ratio and contents.
However, in some specifical resolution, images from ImageAnalysis and ImageCapture looks same, but they are wider than image on PreviewView.
I solved this by set scaleType of PreviewView to FIT_CENTER, as its default value is FILL_CENTER, which would cause the preview to be cropped if the camera preview aspect ratio does not match that of its container:
previewView.scaleType = PreviewView.ScaleType.FIT_CENTER
And, to ensure ImageAnalysis aspect ratio is as close to the PreviewView as possible:
val highSize = Size(3000, 4000)
val preview = Preview.Builder().setTargetResolution(highSize).build()
val imgCaptured = ImageCapture.Builder().setTargetResolution(highSize).build()
preview.setSurfaceProvider(previewView.surfaceProvider)
// bind empty lifycycle with id to get camera
val supportSizes = getSupportedSizes(camera, 0)
val analysisSize = getNearestSize(supportSizes, 480, 640, 30f)
val analyzer = ImageAnalysis.Builder()
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .setOutputImageRotationEnabled(true)
            .setTargetResolution(analysisSize).build()
analyzer.setAnalyzer(...)
cameraProvider.unbindAll()
val camera = cameraProvider.bindToLifecycle(lifecycle, cameraSelector, preview, imgCaptured, analyzer)
fun getSupportedSizes(camera: Camera, device: Int): Array<Size!>{
    val cInfo = camera.cameraInfo
    val camChars = Camera2CameraInfo.extractCameraCharacteristics(cInfo)
    val configs: StreamConfigurationMap? =
        camChars.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
    if (configs == null) {
        Log.i(TAG, "get camera out sizes fail, config empty")
        return
    }
    val sensorRotate = camChars.get(CameraCharacteristics.SENSOR_ORIENTATION) ?: 0
    return configs.getOutputSizes(ImageFormat.JPEG)
}
fun getNearestSize(sizes: Array<Size!>, inWidth: Int, inHeight: Int, aspectWeight: Float = 1f): Size? {
    if (inWidth <= 0 || inHeight <= 0 || device !in cameraInfoMap) return null
    val requireArea = inWidth * inHeight
    val requireAspect = inHeight * 1f / inWidth
    var bestSize: Size? = null
    var minDiff: Float = 10000f
    Log.i(TAG, "find near size for aspect: ${requireAspect}, $inWidth * $inHeight, weight: $aspectWeight")
    for (size in sizes) {
        val curArea = size.width * 1f * size.height
        val curAspect = size.height * 1f / size.width
        val curDiff = abs(curAspect - requireAspect) * aspectWeight + abs(curArea / requireArea - 1)
        if (bestSize == null || minDiff > curDiff) {
            Log.i(TAG, "better size: $size, diff: $curDiff")
            bestSize = size
            minDiff = curDiff
        }
    }
    return bestSize
}
Finally, I can get small resolution image for analysis, and high resolution for preview and capture, which has same aspect ratio and looks same!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With