hjam40 / Camera.MAUI

A CameraView Control for preview, take photos and control the camera options
MIT License
436 stars 69 forks source link

poor image quality #42

Open jarvis10211 opened 1 year ago

jarvis10211 commented 1 year ago

Camera view quality is very bad & blurry therefore barcode detection not working properly. How to increase image qualty or resolution?

hjam40 commented 1 year ago

Platform?? Are you talking about preview, photo, snaphot, video? In the Camera property (CameraInfo class) you have a property AvailableResolutions with the camera supported resolutions

jarvis10211 commented 1 year ago

bad image quality in barcode scan camera viewfinder at both IOS and android

Maryusz commented 1 year ago

I use this library to scan qr codes too, and I have the same issue I suppose. Using the code from the documentation when a tab shows the preview of the qr code it gets really strange effect on the camera, like the camera starts with a very low and blurry resolution.

        {
            cameraView.Camera = cameraView.Cameras.First();
            MainThread.BeginInvokeOnMainThread(async () =>
            {
                try
                {
                    if (cameraView != null && await cameraView.StartCameraAsync() == CameraResult.Success)
                    {
                        await Task.Delay(500);
                        cameraView.BarCodeOptions = new Camera.MAUI.ZXingHelper.BarcodeDecodeOptions
                        {
                            AutoRotate = true,
                            PossibleFormats = { ZXing.BarcodeFormat.QR_CODE },
                            ReadMultipleCodes = false,
                            TryHarder = true,
                            TryInverted = true
                        };

                        cameraView.BarCodeDetectionFrameRate = 10;
                        cameraView.BarCodeDetectionMaxThreads = 2;
                        cameraView.ControlBarcodeResultDuplicate = true;
                        cameraView.BarCodeDetectionEnabled = true;
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);

                }
            });
        }

image

When I however 'restart' the view, resolution it's right.

protected override void OnAppearing()
    {
        base.OnAppearing();

        MainThread.BeginInvokeOnMainThread(async () =>
        {
            try
            {
                await cameraView.StartCameraAsync();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

        });
    }

image

Now I tried to select a resolution with Size(x, y) and if I remember well, the issue persist. The difference is that if a Resolution is selected it is better performant (if you have a 4k camera on the phone and you don't select a resolution, it becomes hot from processing the images because it analyzes images in the highest resolution.).

hjam40 commented 1 year ago

Hi,

The behavior is different between platforms. When you call StartCameraAsync with a Size parameter, this resolution is used when you call TakePhotoAsync (in all platforms) and for the preview resolution (only in iOS and Windows). In Android, the plugging sets the preview resolution depending of CameraView control size due a performance issue.

Seeing your photos, the problem sames to be due the camera focus. You could call the ForceAutoFocus method.

manuelgroo commented 1 year ago

I have tried calling the ForceAutoFocus method but I'm getting the same poor quality in my camera, do you have any other idea to solve this?

Maryusz commented 1 year ago

I added too the ForceAutoFocus method call, but actually the problem persists. It seems that at a first start, the camera takes a low resolution, if I restart the camera (in my app on appearing, the camera is restarted) it works fine.

hjam40 commented 1 year ago

Hi,

It same to be a problem in some android devices and I can't do anything to solve it. On Android I set the AutoFocus on when you start the camera (and when you restart it is the same method...)

Vetleskrett commented 1 year ago

I had the same problem. For me the problem was that I called cameraView.StartCameraAsync() before I had set cameraView.Camera. cameraView.Camera was null, but CameraResult was still CameraResult.Success.

ContentPage_Appearing() was called first, then cameraView_CamerasLoaded() was called. This resulted in low resolution for some reason.

    private void ContentPage_Appearing(object sender, EventArgs e)
    {
        MainThread.BeginInvokeOnMainThread(async () =>
        {
            await cameraView.StopCameraAsync();
            await cameraView.StartCameraAsync();
        });
    }
    private void cameraView_CamerasLoaded(object sender, EventArgs e)
    {
        MainThread.BeginInvokeOnMainThread(async () =>
        {
            if (cameraView.Cameras.Count > 0)
            {
                cameraView.Camera = cameraView.Cameras.First();

                await cameraView.StopCameraAsync();
                await cameraView.StartCameraAsync();
            }
        });
    }

I simply solved it by adding a if check. Also, it only worked if I stopped before starting for some reason.

    private void ContentPage_Appearing(object sender, EventArgs e)
    {
        MainThread.BeginInvokeOnMainThread(async () =>
        {
            if (cameraView.Camera is not null)
            {
                await cameraView.StopCameraAsync();
                await cameraView.StartCameraAsync();
            }
        });
    }
Maryusz commented 1 year ago

I'll try the same approach tomorrow, thank for the suggestion @Vetleskrett 👍

kennykanp commented 11 months ago

It's strange that this happens. In my case, I'm currently working around the issue like this:

await cameraView.StopCameraAsync();
await cameraView.StartCameraAsync();
await Task.Delay(TimeSpan.FromSeconds(3));
if (!cameraView.IsFocused)
{
    await cameraView.StopCameraAsync();
    await cameraView.StartCameraAsync(cameraView.Camera.AvailableResolutions.OrderByDescending(size => size.Width * size.Height).FirstOrDefault());
    cameraView.ForceAutoFocus();
}

This workaround seems to resolve the problem, but it would be great to find a more permanent solution.

Robula commented 11 months ago

Same quality issue if starting the camera too early, I am working around this by adding Task.Delay(1); before I start the camera.

Without workaround: image

With workaround: image

Here is my code:

public partial class CameraPage : ContentPage, IAsyncDisposable
{
    public CameraPage()
    {
        InitializeComponent();

        CameraView.CamerasLoaded += CameraView_CamerasLoaded;
        CameraView.BarcodeDetected += CameraViewOnBarcodeDetected;
        CameraView.Loaded += CameraViewOnLoaded;
    }

    private async void CameraViewOnLoaded(object? sender, EventArgs e)
    {
        CameraView.Loaded -= CameraViewOnLoaded;
        await Task.Delay(1);  // Workaround
        await CameraView.StartCameraAsync();
    }

    // Omitted
}
UnreachableCode commented 7 months ago

@Vetleskrett's workaround worked for me. I don't think it's a good idea to rely on Task.Delay because you can't be sure how different devices are going to handle time related code.

mdjavedakhtar commented 3 months ago

i am still having the same issue on android the available resolutions are showing 0 image is too low resolution !!

DanielWooldridge1 commented 1 week ago

Has there been any updates on this issue?