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 设备传输图像时,我遇到了类似的问题。如果您的问题相同,您可以通过多种方式解决:
通过 USB 网络共享传输数据,它通常比 wifi 或蜂窝网络快得多,甚至可以传输未经压缩的原始图像流,分辨率为 30 fps 640x480。对于 Jpeg,我认为您将能够以 30 fps 的速度流式传输 FullHD。
将 phone 上的数据保存到 ROS Bag http://wiki.ros.org/rosbag and then work with the data. Here you miss realtime, but sometimes it's not needed. To make it I actually wrote an application for android https://github.com/lamerman/ros_android_bag and you can also download it directly from 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 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 设备传输图像时,我遇到了类似的问题。如果您的问题相同,您可以通过多种方式解决:
通过 USB 网络共享传输数据,它通常比 wifi 或蜂窝网络快得多,甚至可以传输未经压缩的原始图像流,分辨率为 30 fps 640x480。对于 Jpeg,我认为您将能够以 30 fps 的速度流式传输 FullHD。
将 phone 上的数据保存到 ROS Bag http://wiki.ros.org/rosbag and then work with the data. Here you miss realtime, but sometimes it's not needed. To make it I actually wrote an application for android https://github.com/lamerman/ros_android_bag and you can also download it directly from 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
通过网络传输的问题对于原始图像肯定是实际的,但如果图像尺寸大且帧率高,也可能是压缩图像。