2015-08-18 12 views
5

में एंड्रॉइड 5.0 में कैमरा 2 एपीआई का उपयोग करके प्रत्येक फ्रेम डेटा कैसे प्राप्त करें मैं अब camera2Basic के साथ काम कर रहा हूं और प्रत्येक फ्रेम डेटा को कुछ छवि प्रसंस्करण करने की कोशिश कर रहा हूं। मैं एंड्रॉइड 5.0 में कैमरा 2 एपीआई का उपयोग कर रहा हूं, कैमरा पूर्वावलोकन करने पर यह सब कुछ ठीक है और यह द्रव है। लेकिन पूर्वावलोकन जब मैं प्रत्येक फ्रेम डेटा प्राप्त करने के लिए ImageReader.OnImageAvailableListener कॉलबैक का उपयोग करता हूं, तो यह खराब उपयोगकर्ता अनुभव का कारण बनता है। पीछा कर रहा है मेरी संबंधित कोड:रीयलटाइम

इस कैमरे और ImageReader के लिए सेटअप है, मैं सेट छवि के प्रारूप YUV_420_888

public<T> Size setUpCameraOutputs(CameraManager cameraManager,Class<T> kClass, int width, int height) { 
    boolean flagSuccess = true; 
    try { 
     for (String cameraId : cameraManager.getCameraIdList()) { 
      CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId); 
      // choose the front or back camera 
      if (FLAG_CAMERA.BACK_CAMERA == mChosenCamera &&   
        CameraCharacteristics.LENS_FACING_BACK != characteristics.get(CameraCharacteristics.LENS_FACING)) { 
       continue; 
      } 
      if (FLAG_CAMERA.FRONT_CAMERA == mChosenCamera && 
        CameraCharacteristics.LENS_FACING_FRONT != characteristics.get(CameraCharacteristics.LENS_FACING)) { 
       continue; 
      } 
      StreamConfigurationMap map = characteristics.get(
        CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 

      Size largestSize = Collections.max(
        Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)), 
        new CompareSizesByArea()); 

      mImageReader = ImageReader.newInstance(largestSize.getWidth(), largestSize.getHeight(), 
        ImageFormat.YUV_420_888, 3); 

      mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler); 
      ... 
      mCameraId = cameraId; 
     } 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } catch (NullPointerException e) { 

    } 
    ...... 
} 

है जब कैमरा सफलतापूर्वक खोला, मैं कैमरा पूर्वावलोकन

के लिए एक CameraCaptureSession बनाएं
private void createCameraPreviewSession() { 
    if (null == mTexture) { 
     return; 
    } 

    // We configure the size of default buffer to be the size of camera preview we want. 
    mTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 

    // This is the output Surface we need to start preview 
    Surface surface = new Surface(mTexture); 

    // We set up a CaptureRequest.Builder with the output Surface. 
    try { 
     mPreviewRequestBuilder = 
       mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
     mPreviewRequestBuilder.addTarget(mImageReader.getSurface()); 
     mPreviewRequestBuilder.addTarget(surface); 

     // We create a CameraCaptureSession for camera preview 
     mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), 
       new CameraCaptureSession.StateCallback() { 

        @Override 
        public void onConfigured(CameraCaptureSession session) { 
         if (null == mCameraDevice) { 
          return; 
         } 

         // when the session is ready, we start displaying the preview 
         mCaptureSession = session; 

         // Finally, we start displaying the camera preview 
         mPreviewRequest = mPreviewRequestBuilder.build(); 
         try { 
          mCaptureSession.setRepeatingRequest(mPreviewRequest, 
            mCaptureCallback, mBackgroundHandler); 
         } catch (CameraAccessException e) { 
          e.printStackTrace(); 
         } 
        } 

        @Override 
        public void onConfigureFailed(CameraCaptureSession session) { 

        } 
       }, null); 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 
} 

पिछले ImageReader.OnImageAvailableListener कॉलबैक

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() { 
      @Override 
      public void onImageAvailable(ImageReader reader) { 
       Log.d(TAG, "The onImageAvailable thread id: " + Thread.currentThread().getId()); 
       Image readImage = reader.acquireLatestImage(); 
       readImage.close(); 
      } 
     }; 
है 0

शायद मैं गलत सेटअप करता हूं लेकिन मैं कई बार कोशिश करता हूं और यह काम नहीं करता है। शायद ImageReader के बजाय फ्रेम डेटा प्राप्त करने का एक और तरीका है लेकिन मुझे नहीं पता। कोई भी जानता है कि रीयलटाइम में प्रत्येक फ्रेम डेटा कैसे प्राप्त करें?

+0

आप किस प्रकार की प्रसंस्करण करने की कोशिश कर रहे हैं? मुझे लगता है कि अगर आप छवि को सहेजना चाहते हैं, तो एक छवि रीडर का उपयोग करें, लेकिन यदि आप कुशल रीयल-टाइम प्रोसेसिंग करना चाहते हैं, तो आपको इसके बजाय आवंटन से जुड़े भूतल बफर को डेटा भेजना चाहिए। – rcsumner

+0

@ सुमनर, मैं कैमरे से प्रत्येक फ्रेम प्राप्त करना चाहता हूं और छवि को सहेजने के बजाय चेहरे का पता लगाना चाहता हूं। ऐसा लगता है कि आपके द्वारा प्रदान किया जाने वाला समाधान अच्छा है, क्या आप अधिक जानकारी दे सकते हैं? – CJZ

+0

... हाहा वास्तव में नहीं, क्षमा करें। मैं आमतौर पर सिर्फ अपने उद्देश्यों के लिए छवियों को बचाता हूं। मुझे पता है कि इसमें रेंडरस्क्रिप्ट का उपयोग करना शामिल है, हालांकि। आवंटन वर्ग दस्तावेज देखें। – rcsumner

उत्तर

0

मैं एक ही बातें कोशिश कर रहा हूँ, मुझे लगता है कि आप की तरह

mImageReader = ImageReader.newInstance(largestSize.getWidth(), 
             largestSize.getHeight(), 
             ImageFormat.FLEX_RGB_888, 3); 

स्वरूप बदल सकता है क्योंकि YUV का उपयोग कर डेटा को संपीड़ित करने के सीपीयू कारण हो सकता है और यह कुछ समय खर्च कर सकते हैं। आरजीबी सीधे डिवाइस पर दिखाया जा सकता है। और छवि से चेहरे का पता लगाना चाहिए अन्य थ्रेड में आपको यह पता होना चाहिए।

1

मुझे विश्वास नहीं है कि चेन सही है। मेरे द्वारा परीक्षण किए गए उपकरणों पर छवि प्रारूप की गति पर लगभग 0 प्रभाव पड़ता है। इसके बजाए, समस्या छवि आकार के साथ प्रतीत होती है।

[1600x1200, 1280x720, 960x720, 720x480, 640x480, 480x320, 320x240, 176x144] 

इन संबंधित आकार के लिए, अधिकतम एफपीएस मैं जब एक लक्ष्य के रूप mImageReader.getSurface() की स्थापना मिलती है: छवि प्रारूप YUV_420_888 के साथ एक एक्सपीरिया जेड 3 कॉम्पैक्ट पर, मैं StreamConfigurationMap के getOutputSizes विधि में विभिन्न विकल्पों में से एक गुच्छा की पेशकश कर रहा हूँ mPreviewRequestBuilder के लिए कर रहे हैं:

[13, 18, 25, 28, 30, 30, 30, 30 ] 

तो एक समाधान दर यदि आप चाहते प्राप्त करने के लिए और कम रिज़ॉल्यूशन का प्रयोग है। जिज्ञासु के लिए ... ध्यान रहे कि ये समय लाइन द्वारा प्रभावित हो सकते हैं नहीं है

mPreviewRequestBuilder.addTarget(surface); 
... 
    mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), 

मुझे चिंता है कि स्क्रीन पर सतह जोड़ने भूमि के ऊपर जोड़ने हो सकता था, लेकिन अगर मुझे लगता है कि हटाने पहली पंक्ति और परिवर्तन दूसरा

mCameraDevice.createCaptureSession(Arrays.asList(mImageReader.getSurface()), 

तो मुझे समय 1 एफपीएस से कम समय में परिवर्तन दिखाई देता है। इसलिए यह कोई फर्क नहीं पड़ता कि आप स्क्रीन पर छवि प्रदर्शित कर रहे हैं या नहीं।

मुझे लगता है कि कैमरा 2 एपीआई या इमेज रीडर के ढांचे में कुछ ओवरहेड है जो TextureView को स्पष्ट रूप से प्राप्त होने वाली पूर्ण दर प्राप्त करना असंभव बनाता है।

सभी की सबसे निराशाजनक चीजों में से एक यह है कि, यदि आप बहिष्कृत कैमरा एपीआई पर वापस स्विच करते हैं, तो आप Camera.setPreviewCallbackWithBuffer विधि के माध्यम से PreviewCallback सेट करके आसानी से 30 एफपीएस प्राप्त कर सकते हैं।उस विधि के साथ, मैं संकल्प के बावजूद 30fps प्राप्त करने में सक्षम हूं। विशेष रूप से, हालांकि यह मुझे 1600x1200 सीधे प्रदान नहीं करता है, यह 1920x1080 की पेशकश करता है, और यहां तक ​​कि यह 30fps भी है।

संबंधित मुद्दे