Android 摄像头图像实时传输到ROS遇到OOM问题?

Android camera image transport to ROS in real-time have an OOM trouble?

我正在尝试将图像信息从 Android Camera 传输到 ROS 实时。但是,我遇到了 OOM 问题。我刚接触Android-ROS,几乎没有处理过此类问题的经验。

下面是我的演示的一些信息:(如果大家需要更多,请评论)

1.

public class MainActivity extends RosActivity implements NodeMain, SurfaceHolder.Callback, Camera.PreviewCallback

2.Dependencies Opencv-for-Android(3.2.0).

3.ROS 消息类型:android_cv_bridge.

我正在尝试在 onPreviewFrame() 函数中发布图像消息。代码如下:

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    Camera.Size size = camera.getParameters().getPreviewSize();
    YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
    Bitmap bmp = null;

    if(yuvImage != null){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, baos);
        bmp = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.size());

        try{
            baos.flush();
            baos.close();
        }
        catch(IOException e){
            e.printStackTrace();
        }

        image = imagePublisher.newMessage();
        Time curTime = connectedNode.getCurrentTime();

        image.setEncoding("rgba8");
        image.getHeader().setStamp(curTime);
        image.getHeader().setFrameId("camera");

        curTime = null;

        if(isOpenCVInit){
            Mat mat_image = new Mat(bmp.getHeight(), bmp.getWidth(), CvType.CV_8UC4, new Scalar(0));
            Bitmap copyBmp = bmp.copy(Bitmap.Config.ARGB_8888, true);

            // bitmap to mat
            Utils.bitmapToMat(copyBmp, mat_image);
            // mat to cvImage
            CvImage cvImage = new CvImage(image.getHeader(), "rgba8", mat_image);

            try {
                imagePublisher.publish(cvImage.toImageMsg(image));
            } catch (IOException e) {
                e.printStackTrace();
            }

            mat_image.release();
            mat_image = null;

            if(!bmp.isRecycled()) {
                bmp.recycle();
                bmp = null;
            }
            if(!copyBmp.isRecycled()) {
                copyBmp.recycle();
                copyBmp = null;
            }
            cvImage =null;
            image = null;
        }
    }

    yuvImage = null;
    System.gc();
}

这里初始化了imagePublisher

@Override
public void onStart(ConnectedNode connectedNode) {
    this.connectedNode = connectedNode;
    imagePublisher = connectedNode.newPublisher(topic_name, sensor_msgs.Image._TYPE);
}

好吧,我已经尽力避免了 OOM 的问题。我还尝试不应用 OpenCV,而只是处理 bitmap像这样:

ChannelBufferOutputStream cbos = new ChannelBufferOutputStream(MessageBuffers.dynamicBuffer());

bmp.compress(Bitmap.CompressFormat.JPEG, 80, baos);
cbos.buffer().writeBytes(baos.toByteArray());
image.setData(cbos.buffer().copy());

cbos.buffer().clear();
imagePublisher.publish(image);

不幸的是,情况变得更糟了。我怀疑我试图实现这个目标的方式。或者有更好的方法吗?

我认为您的问题可能是您的网络无法传输这么多图像数据,而 OOM 是由尚未传输的缓冲区中滞留的数据引起的。

当我想从我的 android 设备传输图像时,我遇到了类似的问题。如果您的问题相同,您可以通过多种方式解决:

关于您第二次尝试传输 JPEG 而不是 RAW 数据,请查看此源代码,此处已正确实现https://github.com/rosjava/android_core/blob/kinetic/android_10/src/org/ros/android/view/camera/CompressedImagePublisher.java#L80

通过网络传输的问题对于原始图像肯定是实际的,但如果图像尺寸大且帧率高,也可能是压缩图像。