Проблема преобразования YUV в RGB ImageReader с Android Camera2 с помощью OpenCV, выходное изображение в оттенках серого - PullRequest
0 голосов
/ 06 апреля 2019

Я пытаюсь преобразовать изображение из YUV в RGB внутри метода onImageAvailable в Java.

Я использую openCV для конвертации. Я не могу использовать формат RGB с Android Camera2, чтобы избежать потери кадров.

Я не могу выбрать лучший формат для конвертации.

Image.Plane Y = image.getPlanes()[0];
Image.Plane U = image.getPlanes()[1];
Image.Plane V = image.getPlanes()[2];

Y.getBuffer().position(0);
U.getBuffer().position(0);
V.getBuffer().position(0);

int Yb = Y.getBuffer().remaining();
int Ub = U.getBuffer().remaining();
int Vb = V.getBuffer().remaining();

ByteBuffer buffer = ByteBuffer.allocateDirect( Yb + Ub + Vb);

buffer.put(Y.getBuffer());
buffer.put(U.getBuffer());
buffer.put(V.getBuffer());

// Image is 640 x 480
Mat yuvMat = new Mat(960, 640, CvType.CV_8UC1);
yuvMat.put(0, 0, buffer.array());

// I don't know what is the correct format 
Mat rgbMat = new Mat(yuvMat.rows, yuvMat.cols, CvType.CV_8UC4);
Imgproc.cvtColor(yuvMat, rgbMat, Imgproc.COLOR_YUV420sp2RGBA);

final Bitmap bit = Bitmap.createBitmap(rgbMat.cols(), rgbMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(rgbMat, bit);

На самом деле я получаю только обрезанное изображение в оттенках серого

1 Ответ

0 голосов
/ 06 апреля 2019

Попробуйте эту функцию:

    void decodeYUV420SP( byte[] rgb, byte[] yuv420sp, int width, int height )
{
    final int frameSize = width * height;

    for (int j = 0, yp = 0; j < height; j++) {
        int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
        for (int i = 0; i < width; i++, yp++) {
            int y = (0xff & ((int) yuv420sp[yp])) - 16;
            if (y < 0)
                y = 0;
            if ((i & 1) == 0) {
                v = (0xff & yuv420sp[uvp++]) - 128;
                u = (0xff & yuv420sp[uvp++]) - 128;
            }

            int y1192 = 1192 * y;
            int r = (y1192 + 1634 * v);
            int g = (y1192 - 833 * v - 400 * u);
            int b = (y1192 + 2066 * u);

            if (r < 0)                  r = 0;               else if (r > 262143)
                r = 262143;
            if (g < 0)                  g = 0;               else if (g > 262143)
                g = 262143;
            if (b < 0)                  b = 0;               else if (b > 262143)
                b = 262143;

            //rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
            int nIdx = ((width - i - 1) * height + height - j - 1) * 3;//device
            //int nIdx = (i * height + j) * 3;//nox
            rgb[nIdx] = (byte) (((r << 6) & 0xff0000)>>16);
            rgb[nIdx+1] = (byte) (((g >> 2) & 0xff00)>>8);
            rgb[nIdx+2] = (byte) ((b >> 10) & 0xff);
        }
    }
}

Использование: decodeYUV420SP (rgb, camData, nWidth234, nHeight234);

Вы можете получить байтовый массив RGB;

Если вам нужно получить изображение из байтового массива, попробуйте это.

    public boolean convertYunToJpeg(byte[] data, int width, int height){
    YuvImage image = new YuvImage(data, ImageFormat.NV21, width, height, null);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int quailty = 20;
    image.compressToJpeg(new Rect(0,0, width, height), quailty, baos);
    byte[] jpegByteArray = baos.toByteArray();
    Bitmap bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length);
    Matrix matrix = new Matrix();
    matrix.postRotate(-90);
    Bitmap lastbitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    try {

        File file = new File(BaseApplication.DIRECTORY + mCode + ".png");
        if(!file.exists()){
            RandomAccessFile me = new RandomAccessFile(BaseApplication.DIRECTORY + mCode + ".png", "rw");
            me.writeInt(5);
            me.close();
            file = new File(BaseApplication.DIRECTORY + mCode + ".png");
        }
        FileOutputStream fos = new FileOutputStream(file);
        lastbitmap.compress(Bitmap.CompressFormat.PNG, quailty, fos);
    } catch (IOException e) {
        e.printStackTrace();
        return  false;
    }
    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...