2017-05-22 17 views
0

私はリアルタイムでROSAndroidのカメラから画像情報を転送しようとしています。しかし、私はOOMの問題があります。私はAndroid-ROSに新しいです、ほとんどそのような問題に対処する経験がありません。リアルタイムでROSへのAndroidカメラ画像の転送にOOMの問題がありますか?

Here're私のデモのいくつかの情報:(君たちはplsは、より多くのコメントが必要な場合)

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のを適用しないようにしよう、とだけビットマップこのようなを扱っていました:

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); 

残念ながら、それは悪化です。私はこの目標を達成しようとしている方法を疑う。それとも良い方法がありますか?

答えて

0

あなたのネットワークがこの量のイメージデータを転送することができず、OOMがまだ転送されていないバッファにスタックされたデータによって引き起こされている可能性があります。

私はAndroidデバイスから画像を転送したいときに同様の問題が発生しました。あなたの問題は同じであるならば、あなたはいくつかの方法でそれを解決することができます:USBテザリング経由

  • 転送データを、それははるかに高速無線LANや携帯よりも一般的だと30 fpsの640×480に圧縮しなくても、生の画像ストリームを転送することができます。 Jpegの場合、30fpsでFullHDをストリーミングできると思います。

  • 携帯電話のデータをROSバッグhttp://wiki.ros.org/rosbagに保存し、データを処理します。ここであなたはリアルタイムでミスしますが、時にはそれは必要ではありません。それを作るために(画像サイズ、FPSを下げる)か、ネットワークの品質を向上させる、私は実際にはアンドロイドhttps://github.com/lamerman/ros_android_bagのためのアプリケーションを書いて、あなたはまた、さらに帯域幅を減少させることがhttps://play.google.com/store/apps/details?id=org.lamerman.rosandroidbag&hl=en

  • 試みをGoogle Playから直接ダウンロードすることができます

代わりに、RAWデータのJPEGを転送すると、あなたの第二の試みについて

、このソースコードを見て、それが正しくhttps://github.com/rosjava/android_core/blob/kinetic/android_10/src/org/ros/android/view/camera/CompressedImagePublisher.java#L80

実現していますここでは、ネットワークを介し転送の問題が生のイメージのため実際の確かですが、あってもよいですコンプ画像のサイズが大きく、フレームレートが高い場合は、画像を縮小します。

+0

とにかく、私はこの問題を良い方法で解決しましたが、完璧ではありませんでした。私は** sensor_msgs.compressedImage **タイプしか公開できません。** FPS **、サブスレッドではもっとうまくやってください**メモリ**を保存します。そして最後に、私のプログラムを最適化するために多くの良い提案を提供してくれてありがとう!再度、感謝します! –

関連する問題