android एंड्रॉइड एल और कैमरा 2 एपीआई के साथ कैमरा पूर्वावलोकन छवि डेटा प्रोसेसिंग



image-processing camera (4)

मैं एक एंड्रॉइड ऐप पर काम कर रहा हूं जो कैमरे से इनपुट छवि को प्रोसेस कर रहा है और इसे उपयोगकर्ता को प्रदर्शित करता है। यह काफी सरल है, मैं कैमरा ऑब्जेक्ट पर setPreviewCallbackWithBuffer साथ एक PreviewCallback पंजीकृत करता setPreviewCallbackWithBuffer । यह आसान है और पुराने कैमरा एपीआई के साथ आसानी से काम करता है

public void onPreviewFrame(byte[] data, Camera cam) {
    // custom image data processing
}

मैं नए ऐप 2 एपीआई का लाभ उठाने के लिए अपने ऐप को बंद करने की कोशिश कर रहा हूं और मुझे यकीन नहीं है कि मैं इसे कैसे करूँगा। मैंने एल पूर्वावलोकन नमूने में कैमरा 2 वीडियो का पालन किया जो एक वीडियो रिकॉर्ड करने की अनुमति देता है। हालांकि, नमूना में कोई प्रत्यक्ष छवि डेटा स्थानांतरण नहीं है, इसलिए मुझे समझ में नहीं आता कि मुझे छवि पिक्सेल डेटा कहां मिलेगा और इसे कैसे संसाधित किया जाए।

क्या कोई मेरी मदद कर सकता है या सुझाव दे सकता है कि एंड्रॉइड एल में PreviewCallback की कार्यक्षमता कैसे प्राप्त हो सकती है, या स्क्रीन पर इसे प्रदर्शित करने से पहले कैमरा से पूर्वावलोकन डेटा को संसाधित करना संभव है? (कैमरा ऑब्जेक्ट पर कोई पूर्वावलोकन कॉलबैक नहीं है)

धन्यवाद!


मुझे एक ही चीज़ की ज़रूरत थी, इसलिए मैंने उनका उदाहरण इस्तेमाल किया और कैमरे को पूर्वावलोकन स्थिति में होने पर एक नए समारोह में कॉल जोड़ा।

private CameraCaptureSession.CaptureCallback mCaptureCallback
            = new CameraCaptureSession.CaptureCallback()
    private void process(CaptureResult result) {
        switch (mState) {
            case STATE_PREVIEW: {
                    if (buttonPressed){
                        savePreviewShot();
                    }
                break;
            }

savePreviewShot() केवल savePreviewShot() का उपयोग करने के लिए अनुकूलित मूल savePreviewShot() का एक पुनर्नवीनीकरण संस्करण है।

   private void savePreviewShot(){
        try {
            final Activity activity = getActivity();
            if (null == activity || null == mCameraDevice) {
                return;
            }
            // This is the CaptureRequest.Builder that we use to take a picture.
            final CaptureRequest.Builder captureBuilder =
                    mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureBuilder.addTarget(mImageReader.getSurface());

            // Orientation
            int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));

            CameraCaptureSession.CaptureCallback CaptureCallback
                    = new CameraCaptureSession.CaptureCallback() {

                @Override
                public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                                               TotalCaptureResult result) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss:SSS");
                    Date resultdate = new Date(System.currentTimeMillis());
                    String mFileName = sdf.format(resultdate);
                    mFile = new File(getActivity().getExternalFilesDir(null), "pic "+mFileName+" preview.jpg");

                    Log.i("Saved file", ""+mFile.toString());
                    unlockFocus();
                }
            };

            mCaptureSession.stopRepeating();
            mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    };

चूंकि Camera एपीआई वर्तमान Camera एपीआई से बहुत अलग है, इसलिए यह दस्तावेज़ीकरण के माध्यम से जाने में मदद कर सकता है।

एक अच्छा प्रारंभिक बिंदु camera2basic उदाहरण है। यह दर्शाता है कि Camera2 एपीआई का उपयोग कैसे करें और जेपीईजी छवियों को प्राप्त करने के लिए ImageReader को कॉन्फ़िगर करें और ImageReader.OnImageAvailableListener को उन छवियों को प्राप्त करने के लिए पंजीकृत करें

पूर्वावलोकन फ्रेम प्राप्त करने के लिए, आपको अपनी ImageReader की सतह को setRepeatingRequest के CaptureRequest.Builder जोड़ने की आवश्यकता है।

साथ ही, आपको ImageReader का प्रारूप YUV_420_888 सेट करना चाहिए, जो आपको 8 एमपी पर 30fps देगा (दस्तावेज़ीकरण नेक्सस 5 के लिए 8 एमपी पर 30fps की गारंटी देता है)।


कुछ उत्तरों को अधिक पचाने वाले में जोड़ना क्योंकि @ वीपी का जवाब, तकनीकी रूप से स्पष्ट होने पर, यह समझना मुश्किल है कि क्या यह पहली बार कैमरा से कैमरा 2 तक चल रहा है:

शुरुआती बिंदु के रूप में https://github.com/googlesamples/android-Camera2Basic का उपयोग करके, निम्न संशोधित करें:

mImageReader createCameraPreviewSession() mImageReader से एक नई Surface को mImageReader

Surface mImageSurface = mImageReader.getSurface();

अपने CaptureRequest.Builder परिवर्तक के आउटपुट लक्ष्य के रूप में उस नई सतह को जोड़ें। कैमरा 2 बेसिक नमूना का उपयोग करके, चर mPreviewRequestBuilder होगा

mPreviewRequestBuilder.addTarget(mImageSurface);

नई लाइनों के साथ स्निपेट यहां है (मेरी @ एंजेलो टिप्पणियां देखें):

private void createCameraPreviewSession() {

    try {

        SurfaceTexture texture = mTextureView.getSurfaceTexture();
        assert texture != null;

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

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

        //@AngeloS - Our new output surface for preview frame data
        Surface mImageSurface = mImageReader.getSurface();

        // We set up a CaptureRequest.Builder with the output Surface.
        mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

        //@AngeloS - Add the new target to our CaptureRequest.Builder
        mPreviewRequestBuilder.addTarget(mImageSurface);

        mPreviewRequestBuilder.addTarget(surface);

        ...

अगला, setUpCameraOutputs() , ImageFormat.JPEG से ImageFormat.JPEG पर प्रारूप को ImageFormat.YUV_420_888 जब आप अपने ImageReader init करते हैं। (पीएस, मैं चिकनी ऑपरेशन के लिए अपने पूर्वावलोकन आकार को छोड़ने की भी सिफारिश करता हूं - कैमरा 2 की एक अच्छी सुविधा)

mImageReader = ImageReader.newInstance(largest.getWidth() / 16, largest.getHeight() / 16, ImageFormat.YUV_420_888, 2);

अंत में, ImageReader.OnImageAvailableListener की आपकी onImageAvailable() विधि में, @ कमला के सुझाव का उपयोग करना सुनिश्चित करें क्योंकि पूर्वावलोकन कुछ फ्रेम के बाद बंद हो जाएगा यदि आप इसे बंद नहीं करते हैं

    @Override
    public void onImageAvailable(ImageReader reader) {

        Log.d(TAG, "I'm an image frame!");

        Image image =  reader.acquireNextImage();

        ...

        if (image != null)
            image.close();
    }

ImageReader.OnImageAvailableListener क्लास में, नीचे दिखाए गए अनुसार पढ़ने के बाद छवि को बंद करें (यह अगले कैप्चर के लिए बफर जारी करेगा)। आपको करीब अपवाद को संभालना होगा

      Image image =  imageReader.acquireNextImage();
      ByteBuffer buffer = image.getPlanes()[0].getBuffer();
      byte[] bytes = new byte[buffer.remaining()];
      buffer.get(bytes);
      image.close();




android-5.0-lollipop