在ROS-Android中发布/订阅时,sensor_msgs.image / compressedImage类型的消息大小会发生变化吗?

时间:2017-08-18 11:05:48

标签: android ros

我需要从 Android-phone-camera 获取预览图片数据并通过 发布ROS ,这是我的示例代码:

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

        if(yuvImage != null){
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ChannelBufferOutputStream stream = new ChannelBufferOutputStream(MessageBuffers.dynamicBuffer());

            yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 80, baos);
            yuvImage = null;

            stream.buffer().writeBytes(baos.toByteArray());
            try{
                baos.flush();
                baos.close();
                baos = null;
            }
            catch(IOException e){
                e.printStackTrace();
            }

            // compressedImage type
            sensor_msgs.CompressedImage compressedImage = compressedImagePublisher.newMessage();
            compressedImage.getHeader().setFrameId("xxx");    // frame id

            Time curTime = connectedNode.getCurrentTime();    
            compressedImage.getHeader().setStamp(curTime);    // time

            compressedImage.setFormat("jpeg");                // format
            compressedImage.setData(stream.buffer().copy());  // data

            stream.buffer().clear();
            try {
                stream.flush();
                stream.close();
                stream = null;
            }
            catch (IOException e) {
                e.printStackTrace();
            }

            // publish
            System.out.println("-----Publish: " + compressedImage.getData().array().length + "-----");
            compressedImagePublisher.publish(compressedImage);
            compressedImage = null;
            System.gc();
        }
        else{
            Log.v("Log_Tag", "-----Failed to get yuvImage!-----");
        }
    }
    else{
        Log.v("Log_Tag", "-----Failed to get the preview frame!-----");
    }
}

然后,我订阅了 主题 ,只是为了检查邮件是否已完全正确发布。就像下面的代码一样:

@Override
public void onStart(ConnectedNode node) {
    this.connectedNode = node;

    // publisher
    this.compressedImagePublisher = connectedNode.newPublisher(topic_name, sensor_msgs.CompressedImage._TYPE);
    // subscriber
    this.compressedImageSubscriber = connectedNode.newSubscriber(topic_name, sensor_msgs.CompressedImage._TYPE);
    compressedImageSubscriber.addMessageListener(new MessageListener<CompressedImage>() {
        @Override
        public void onNewMessage(final CompressedImage compressedImage) {
            byte[] receivedImageBytes = compressedImage.getData().array();
            if(receivedImageBytes != null && receivedImageBytes.length != 0) {
                System.out.println("-----Subscribe(+46?): " + receivedImageBytes.length + "-----");

                // decode bitmap from byte[] with a strange number of offset and necessary
                Bitmap bmp = BitmapFactory.decodeByteArray(receivedImageBytes, offset, receivedImageBytes.length - offset);
                ...    
            }
        }
    });
}

我对 偏移量 的数量感到困惑。这意味着在由ROS打包和发布之后图像字节的大小已经改变,并且如果我没有设置偏移,则解码位图将是错误的。更奇怪的是,有时偏移的数量也发生了变化。

我不知道为什么,我读过一些关于 jpg 结构的文章,并怀疑它可能是 jpg字节消息的 head-information 。但是,这个问题恰好发生在 ros-android 场景中。

任何人都对此有好感吗?

OK!我知道我提出的问题和之前描述的问题很糟糕,这就是为什么它得到2个负分。我很抱歉这些,我必须通过告诉你们更多的信息来解决我的错误,现在让问题更加明确。

首先,忘记我之前粘贴的所有代码。问题发生在我的 ros-android 项目中。在这个项目中,我需要将压缩图像类型的传感器消息发送到ros-server,并以发布/订阅方式获取处理后的图像字节(jpg格式)。从理论上讲,图像字节的大小应该相同,事实上,这已经在我的 ros-C ros中得到了证明。 -C# 项目在相同条件下。

然而,他们在ros-android中有所不同,它会变得更大!出于这个原因,我不能从我订阅的图像字节中解码位图,而且我必须在 偏移 中省略这些新的字节。图像字节数组。我不知道为什么会发生在ros-android或ros-java中,以及这些添加部分是什么。

我无法从我的代码中找到原因,这就是我为您详细粘贴代码的原因。我真的需要帮助!提前谢谢!

Logcat

1 个答案:

答案 0 :(得分:0)

也许我真的需要先检查API然后再问问题。如果我在API中检查了 ChannelBuffer 的属性,这是一个非常简单的问题,因为属性arrayOffset已经告诉我这个问题的答案!

嗯,为了更加谨慎,你们中的某些人需要澄清我的答案,所以我必须详细解释一下!

首先,我不得不说,我仍然不知道 ChannelBuffer 如何打包 图像字节数组的数据 ,这意味着我仍然不知道为什么在阵列之前应该有 arrayOffset 数据。为什么我们无法获取数据?成为 arrayOffset 的确有一些重要原因吗?为了安全起见还是效率?我不知道,我无法从API中找到答案。所以我现在真的厌倦了这个问题,而且我已经厌倦了你们是否对这个问题不以为然,只是放手吧!

回到主题,问题可以通过这种方式解决:

int offset = compressedImage.getData().arrayOffset();
Bitmap bmp = BitmapFactory.decodeByteArray(receivedImageBytes, offset, receivedImageBytes.length - offset);

OK!我仍然希望有这方面知识的人可以告诉我为什么,我会如此欣赏这一点!如果你们只是像我一样厌倦了这个问题,那么就让我们投票来关闭它,我也会感激它!不管怎样,谢谢!