将 YUV_420_888 转换为 Base64 Android 损坏图像

发布于 2025-01-12 21:01:40 字数 2540 浏览 6 评论 0原文

我目前正在开发一个项目,该项目在后台模式下使用 OpenCV 在应用程序播放视频时检测人脸。 我已经成功地将 OpenCV 作为服务运行,并且使用 ImageReader 实例来捕获图像

    private ImageReader mImageReader = ImageReader.newInstance(mWidth, mHeight, ImageFormat.YUV_420_888, 1);

我想做的是获取检测到的面部图像并将其发送到后端,来自 Imagereader 的图像被转换为Mat,所以我可以访问 Mat 类型和 Image 类型。 我已成功使用此链接中的 toYuvImage 和 toJpegImage 方法将获取的图像转换为 Yuv 图像,然后转换为 jpg (字节数组):https://blog.minhazav.dev/how-to-convert-yuv-420-sp-android.media.Image-to-Bitmap-or-jpeg/#how-to-convert-yuv_420_888-image- to-jpeg-format

将图像转换为字节数组后,我还尝试将其转换为 base64 以使用 http 发送它,问题是当我尝试将将 toJpegImage 中的 imageQuality 设置为 100 ,base64 图像的结果看起来已损坏,但是当我将值设置为较低的值(例如 15 或 10)时,图像输出(分辨率)更好,但质量很差,我不确定这是否如此问题与分辨率有关

  byte[] jpegDataTest = ImageUtil.toJpegImage(detectionImage,15);
           String base64New = Base64.encodeToString(jpegDataTest, Base64.DEFAULT);

PS:每次在 for 循环中检测到人脸时,我都会转换图像,

        for(Rect rect : faceDetections.toArray()){}

压缩质量设置为 100:https://i.postimg.cc/YqSmFxrT/quality100.jpg

压缩质量设置为15 15 质量

public static byte[] toJpegImage(Image image, int imageQuality) {
    if (image.getFormat() != ImageFormat.YUV_420_888) {
        throw new IllegalArgumentException("Invalid image format");
    }

    YuvImage yuvImage = toYuvImage(image);
    int width = image.getWidth();
    int height = image.getHeight();

    // Convert to jpeg
    byte[] jpegImage = null;
    try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
        yuvImage.compressToJpeg(new Rect(0, 0, width, height), imageQuality, out);
        jpegImage = out.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    }

   return jpegImage;
}

 private static byte[] YUV_420_888toNV21(Image image) {
    byte[] nv21;
    ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
    ByteBuffer vuBuffer = image.getPlanes()[2].getBuffer();

    int ySize = yBuffer.remaining();
    int vuSize = vuBuffer.remaining();

    nv21 = new byte[ySize + vuSize];

    yBuffer.get(nv21, 0, ySize);
    vuBuffer.get(nv21, ySize, vuSize);



    return nv21;
}

I am currently working on a project which uses OpenCV in background mode to detect faces while the app is playing videos .
I've managed to run OpenCV as a service and I am using an ImageReader instance to capture the images

    private ImageReader mImageReader = ImageReader.newInstance(mWidth, mHeight, ImageFormat.YUV_420_888, 1);

What I am trying to do is to get the detected face image and send it to the backend side , the image from the Imagereader is converted to Mat so I have both access to the Mat type and the Image type.
I've managed to convert the aquired image to Yuv image then to jpg ( byte array ) by using both toYuvImage and toJpegImage methods from this link : https://blog.minhazav.dev/how-to-convert-yuv-420-sp-android.media.Image-to-Bitmap-or-jpeg/#how-to-convert-yuv_420_888-image-to-jpeg-format

After converting the image to an array of bytes , I'm also trying to convert it to base64 to send it using http , the problem is when I try to put the imageQuality to 100 in toJpegImage , the result of the base64 image is looking corrupted , but when I put the value to something lower like 15 or 10 the image output ( resolution ) is better but the quality is bad , I am not sure if this problem is related to the resolution

  byte[] jpegDataTest = ImageUtil.toJpegImage(detectionImage,15);
           String base64New = Base64.encodeToString(jpegDataTest, Base64.DEFAULT);

PS : I am converting the image each time a face is detected in a for loop

        for(Rect rect : faceDetections.toArray()){}

compress quality is set to 100 : https://i.postimg.cc/YqSmFxrT/quality100.jpg

compress quality is set to 15
15 quality

public static byte[] toJpegImage(Image image, int imageQuality) {
    if (image.getFormat() != ImageFormat.YUV_420_888) {
        throw new IllegalArgumentException("Invalid image format");
    }

    YuvImage yuvImage = toYuvImage(image);
    int width = image.getWidth();
    int height = image.getHeight();

    // Convert to jpeg
    byte[] jpegImage = null;
    try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
        yuvImage.compressToJpeg(new Rect(0, 0, width, height), imageQuality, out);
        jpegImage = out.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    }

   return jpegImage;
}

 private static byte[] YUV_420_888toNV21(Image image) {
    byte[] nv21;
    ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
    ByteBuffer vuBuffer = image.getPlanes()[2].getBuffer();

    int ySize = yBuffer.remaining();
    int vuSize = vuBuffer.remaining();

    nv21 = new byte[ySize + vuSize];

    yBuffer.get(nv21, 0, ySize);
    vuBuffer.get(nv21, ySize, vuSize);



    return nv21;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文