Захват кадров изображения в формате YUV_420_888 с использованием ImageReader в Camera API 2 не дает правильных результатов на устройствах с двумя камерами - PullRequest
0 голосов
/ 02 января 2019

Я работаю над приложением для Android, которое берет изображение с предварительного просмотра камеры в формате YUV_420_888 и преобразует его в эквивалент RGB.Это приложение для измерения сердечного ритма, которое берет красные рамки с кончика пальца пользователя, когда пользователь касается поверхности камеры.Реализация камеры выполняется с использованием Camera API 2, а кадры изображений захватываются с использованием ImageReader, формат которого установлен в YUV_420_888.

imageReader = ImageReader.newInstance(smallest.getWidth(), smallest.getHeight(), ImageFormat.YUV_420_888, 1);

Кадры изображений, снятые в формате YUV_420_888, затем преобразуются в RGB с помощью следующей функции:

public static double[] decodeYUV420SP_888toRedBlueGreenAvg(byte[] Y1, byte[] U1, byte[] V1, int width, int height) {


    int Width = width;
    int Height = height;
    byte[] ImageRGB = new byte[Width*Height*4];

    double[] rgb =new double[3];
    for(int i = 0; i<Height-1; i++){
        for (int j = 0; j<Width; j++){
            int Y = Y1[i*Width+j]&0xFF -16;
            int U = U1[(i/2)*(Width/2)+j/2]&0xFF;
            int V = V1[(i/2)*(Width/2)+j/2]&0xFF;
            U = U-128;
            V = V-128;
            int R,G,B;

            /*R = (int) (Y + 1.402*(V-128));
            G = (int) (Y - 0.34414 *(U-128) - 0.71414 *(V-128));
            B = (int) (Y + 1.772 *(U-128));*/

           //correct values
            R = (int)(Y + 1.140*V);
            G = (int)(Y - 0.395*U - 0.581*V);
            B = (int)(Y + 2.032*U);



            /*int y1192 = 1192 * Y;
            R = (y1192 + 1634 * V);
            G = (y1192 - 833 * V - 400 * U);
            B = (y1192 + 2066 * U);*/


          /*  Y_temp = 4768 * (Y - 16);
            R = (Y_temp + 6537 * (V - 128)) >> 12;
            G = (Y_temp - 3330 * (V - 128) - 1602 * (U - 128)) >> 12;
            B = (Y_temp + 8266 * (U - 128)) >> 12;*/

          //test
            if (R>255) {
                R = 255;
            } else if (R<0) {
                R = 0;
            }
            if (G>255) {
                G = 255;
            } else if (G<0) {
                G = 0;
            }
            if (B>255) {
                R = 255;
            } else if (B<0) {
                B = 0;
            }


            ImageRGB[i*4*Width+j*4] = (byte)R;
            ImageRGB[i*4*Width+j*4+1] = (byte)G;
            ImageRGB[i*4*Width+j*4+2] = (byte)B;
            ImageRGB[i*4*Width+j*4+3] = -1;
            rgb[0] = R;
            rgb[1] = G;
            rgb[2] = B;
        }
    }


    return rgb;}

Класс сохранения изображения выглядит следующим образом:

 private class ImageSaver implements Runnable {

    byte[] y1, u1, v1;
    int width, height;

    public ImageSaver(byte[] y1, byte[] u1, byte[] v1, int width, int height) {
        this.y1 = y1;
        this.u1 = u1;
        this.v1 = v1;
        this.width = width;
        this.height = height;
    }

    @Override
    public void run() {
        //if data or size == null ****


        if (y1 == null)
            throw new NullPointerException();


        if (textureView == null) throw new NullPointerException();

        current value == the expected value.
        if (!processing.compareAndSet(false, true)) return;


        //put width + height of the camera inside the variables
        int width = textureView.getWidth();
        int height = textureView.getHeight();
        RGBAvg = YUVtoRGB.decodeYUV420SP_888toRedBlueGreenAvg(y1, u1, v1, width, height);

Затем некоторая обработка выполняется с использованием значений rgb.Это нормально работает для устройств с одной камерой, но для устройств с двумя камерами значения rgb отображаются в виде зеленого цвета, а не красного.Особенно в Oppo и некоторых устройствах Redmi, таких как Oppo F9 pro и Redmi 6 pro.

Любая помощь будет высоко оценена!

...