Home > Net >  How to increase image quality with android cameraX library?
How to increase image quality with android cameraX library?

Time:03-07

I am creating an application which must implement its own camera.

I use the cameraX library provided by google.

I noticed that there is a difference between the quality of the image captured by my own application, and the image captured by the camera application installed on my phone.

although the 2 photos are captured with the same conditions (light, position...)

especially when I zoom the photo, the details of the image become more blurry to the image captured by my application

(in my own case, my phone is Google Pixel 5)

Please see these 2 photos to see the difference

Image by phone camera

Image by my app

And this is my code

/**
 *  Initialize CameraX, and prepare to bind the camera use cases
 */
private fun setupCamera()
{
    val cameraProviderFuture : ListenableFuture<ProcessCameraProvider> = ProcessCameraProvider.getInstance(this)
    
    cameraProviderFuture.addListener({
        
        cameraProvider = cameraProviderFuture.get()
        
        lensFacing = when
        {
            hasBackCamera() -> CameraSelector.LENS_FACING_BACK
            hasFrontCamera() -> CameraSelector.LENS_FACING_FRONT
            else -> throw IllegalStateException("Back and front camera are unavailable")
        }
        
        bindCameraUseCases()
        setupCameraGestures()
        
    }, ContextCompat.getMainExecutor(this))
}



/**
 *  Declare and bind preview, capture and analysis use cases.
 */
private fun bindCameraUseCases()
{
    lifecycleScope.launch {
        
        val cameraProvider : ProcessCameraProvider = cameraProvider ?: throw IllegalStateException("Camera initialization failed.")
        
        // Try to apply extensions like HDR, NIGHT ##########################################
        
        val extensionsManager : ExtensionsManager = ExtensionsManager.getInstanceAsync(this@ImageCaptureActivity, cameraProvider).await()
        
        val defaultCameraSelector : CameraSelector = CameraSelector.Builder()
            .requireLensFacing(lensFacing)
            .build()
        
        val finalCameraSelector : CameraSelector = if (extensionsManager.isExtensionAvailable(defaultCameraSelector, ExtensionMode.AUTO))
        {
            extensionsManager.getExtensionEnabledCameraSelector(defaultCameraSelector, ExtensionMode.AUTO)
        }
        else
        {
            defaultCameraSelector
        }
        
        
        // Get screen metrics used to setup camera for full screen resolution
        val metrics : DisplayMetrics = resources.displayMetrics
        
        val screenAspectRatio : Int = aspectRatio(metrics.widthPixels, metrics.heightPixels)
        
        val rotation : Int = binding.cameraPreview.display.rotation
        
        
        preview = Preview.Builder()
            // We request aspect ratio but no resolution
            .setTargetAspectRatio(screenAspectRatio)
            // Set initial target rotation
            .setTargetRotation(rotation)
            .build()
        
        imageCapture = ImageCapture.Builder()
            // We request aspect ratio but no resolution to match preview config, but letting
            // CameraX optimize for whatever specific resolution best fits our use cases
            .setTargetAspectRatio(screenAspectRatio)
            // Set initial target rotation, we will have to call this again if rotation changes
            // during the lifecycle of this use case
            .setTargetRotation(rotation)
            .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
            .setJpegQuality(100)
            .build()
        
        imageAnalyzer = ImageAnalysis.Builder()
            // We request aspect ratio but no resolution
            .setTargetAspectRatio(screenAspectRatio)
            .build()
        
        imageAnalyzer?.setAnalyzer(cameraExecutor, LuminosityAnalyzer {})
        
        // Must unbind the use-cases before rebinding them
        cameraProvider.unbindAll()
        
        try
        {
            // A variable number of use-cases can be passed here -
            // camera provides access to CameraControl & CameraInfo
            camera = cameraProvider.bindToLifecycle(this@ImageCaptureActivity, finalCameraSelector, preview, imageCapture, imageAnalyzer)
            
            // Attach the viewfinder's surface provider to preview use case
            preview?.setSurfaceProvider(binding.cameraPreview.surfaceProvider)
        }
        catch (exception : Exception)
        {
            exception.printStackTrace()
        }
    }
}



/**
 *  [androidx.camera.core.ImageAnalysisConfig] requires enum value of [androidx.camera.core.AspectRatio].
 *  Currently it has values of 4:3 & 16:9.
 *
 *  Detecting the most suitable ratio for dimensions provided in @params by counting absolute
 *  of preview ratio to one of the provided values.
 *
 *  @param width - preview width
 *  @param height - preview height
 *  @return suitable aspect ratio
 */
private fun aspectRatio(width : Int, height : Int) : Int
{
    val previewRatio : Double = max(width, height).toDouble() / min(width, height)
    
    return if (abs(previewRatio - RATIO_4_3_VALUE) <= abs(previewRatio - RATIO_16_9_VALUE))
    {
        AspectRatio.RATIO_4_3
    }
    else
    {
        AspectRatio.RATIO_16_9
    }
}



fun captureImage()
{
    if (!permissionsOk()) return
    
    // Get a stable reference of the modifiable image capture use case
    imageCapture?.let { imageCapture ->
        
        // Create output file to hold the image
        val photoFile : File = storageUtils.createFile(
            baseFolder = getOutputPath(),
            fileName = System.currentTimeMillis().toString(),
            fileExtension = StorageUtils.PHOTO_EXTENSION)
        
        // Setup image capture metadata
        val metadata : Metadata = Metadata().also {
            // Mirror image when using the front camera
            it.isReversedHorizontal = lensFacing == CameraSelector.LENS_FACING_FRONT
            it.location = locationManager.lastKnownLocation
        }
        
        // Create output options object which contains file   metadata
        val outputOptions : ImageCapture.OutputFileOptions = ImageCapture.OutputFileOptions.Builder(photoFile)
            .setMetadata(metadata)
            .build()
        
        imagesAdapter.addImage(photoFile)
        
        // Setup image capture listener which is triggered after photo has been taken
        imageCapture.takePicture(outputOptions, cameraExecutor, object : ImageCapture.OnImageSavedCallback
        {
            override fun onImageSaved(output : ImageCapture.OutputFileResults)
            {
                val savedUri : Uri = output.savedUri ?: return
                
                StorageUtils.showInGallery(savedUri.path)
                
                binding.list.post {
                    imagesAdapter.addImage(savedUri.toFile())
                    binding.list.smoothScrollToPosition(imagesAdapter.itemCount)
                }
            }
            
            override fun one rror(exception : ImageCaptureException)
            {
                exception.printStackTrace()
            }
        })
        
        binding.cameraPreview.postDelayed({
            binding.backgroundEffect.isVisible = true
            binding.cameraPreview.postDelayed({
                binding.backgroundEffect.isVisible = false
            }, AppUtils.VERY_FAST_ANIMATION_MILLIS)
        }, AppUtils.FAST_ANIMATION_MILLIS)
    }
}

How can I improve the quality of my images? Is there any thing I should do? is there a special filter or algorithm?

i need your help please

CodePudding user response:

if you took photo on Pixel probably using default cam app (GCam) - this app is fulfilled with quaility improvements backed up by some AI. tough task to comptetite with the biggest in quality... try to take a photo with some 3rd party like OpenCamera and compare this picture with one got by your app

  • Related