2017-05-22 3 views
0

나는 실시간으로 ROS안드로이드 카메라에서 이미지 정보를 전송하기 위해 노력하고있어. 그러나, 나는 OOM 문제가있다. 나는 에 안주하지 않는다. 안드로이드 -ROS은 거의 그런 문제를 다룰 경험이 없다.실시간으로 ROS에 Android 카메라 이미지 전송시 OOM 문제가 있습니까?

바로 여기에 내 데모의 몇 가지 정보 : (너희들이 더 필요하면 pls는 주석)

1.

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

2.Dependencies 을 OpenCV를 위해 안드로이드 (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이 전송 된 것일 수 있습니다.

내 안드로이드 장치에서 이미지를 전송할 때 비슷한 문제가 발생했습니다. 문제가 같은 경우, 여러 가지 방법으로 그것을 해결할 수 : USB 테 더링을 통해

  • 전송 데이터를 훨씬 빠른 와이파이 또는 셀룰러보다는 일반적이고 30 프레임 640 × 480으로 압축하지 않고 심지어 원시 이미지 스트림을 전송할 수 있습니다. JPEG의 경우 30fps로 FullHD를 스트리밍 할 수 있다고 생각합니다.

  • 휴대 전화의 데이터를 ROS Bag 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

네트워크를 통해 전송의 문제는 확실히 RAW 이미지의 실제이다 구현있어,이 소스 코드를 살펴 가지고 있지만, 또한 할 수있다 광고 문안 작성자 이미지의 크기가 크고 프레임 속도가 높은 경우 이미지를 다시 채 웁니다.

+0

어쨌든 나는이 문제를 좋은 방법으로 해결했지만 완벽하지는 않았습니다. ** sensor_msgs.compressedImage ** 유형 만 게시 할 수 있습니다. ** FPS **, 하위 스레드에서 더 잘 수행하고, ** 메모리 ** 저장. 그리고 마침내 내 프로그램을 최적화 할 수있는 많은 제안을 해주셔서 너무 감사드립니다! 다시 한 번 감사드립니다! –