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

这是我的演示的一些信息:(如果你们需要更多,请发表评论)

1。

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

2.依赖关系 Android(3.2.0)Opencv-ojitrstrong。

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 ,而只是像这样处理位图:
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设备传输图像时,我遇到了类似的问题。如果您的问题相同,则可以通过多种方式解决:

  • 通过USB共享网络传输数据,它通常比wifi或蜂窝网络快得多,并且即使不使用30 fps 640x480压缩也可以传输原始图像流。对于Jpeg,我认为您将能够以30 fps的速度传输FullHD。
  • 将手机上的数据保存到ROS Bag http://wiki.ros.org/rosbag中,然后使用数据。在这里,您会错过实时性,但是有时并不需要。为此,我实际上为android https://github.com/lamerman/ros_android_bag编写了一个应用程序,您也可以直接从Google Play下载https://play.google.com/store/apps/details?id=org.lamerman.rosandroidbag&hl=en
  • 尝试进一步减小带宽(减小图像大小,fps)或提高网络质量

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

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

    关于android - 将Android相机图像实时传输到ROS有OOM麻烦吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44111249/

    10-11 22:30
    查看更多