ตัวอย่างกล้องของฉันจับภาพที่ 1 เฟรมต่อวินาที [ซ้ำกัน]

ขณะนี้แอปพลิเคชันของฉันมีหน้าจอแสดงตัวอย่าง และฉันต้องการให้จับภาพหลายเฟรมต่อวินาทีเพื่อการประมวลผล ในขณะนี้ ตัวอย่างของฉันจะจัดเก็บเฉพาะภาพทุกๆ วินาทีเท่านั้น อย่างไรก็ตาม ฉันต้องการอัตราการจับภาพ fps ที่สูงกว่ามาก ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชม

ปัญหาอีกประการหนึ่ง (ถ้าทำได้) ก็คือรูปภาพของฉันจะหมุน 90 องศาเมื่อปรากฏบนการ์ด SD จนถึงขณะนี้ยังไม่มีวิธีแก้ปัญหาทางอินเทอร์เน็ตที่ช่วยฉันสำหรับปัญหาเหล่านี้ :(

ขอบคุณ :)

    public class MyCameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback{

    private SurfaceHolder mHolder;
    private Camera mCamera;

    public MyCameraSurfaceView(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int weight,
                               int height) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.
        mCamera.setDisplayOrientation(90);

        if (mHolder.getSurface() == null){
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
            // ignore: tried to stop a non-existent preview
        }

        // make any resize, rotate or reformatting changes here

        // start preview with new settings
        try {

            mCamera.setPreviewDisplay(mHolder);
            Camera.Parameters parameters = mCamera.getParameters();
            List<Camera.Size> size = parameters.getSupportedPreviewSizes();
            parameters.setPreviewSize(size.get(0).width, size.get(0).height);
            mCamera.setParameters(parameters);
            mCamera.startPreview();

        } catch (Exception e){}

        mCamera.setPreviewCallback(new Camera.PreviewCallback() {

            public void onPreviewFrame(byte[] data, Camera camera) {

                Camera.Parameters parameters = camera.getParameters();

                int format = parameters.getPreviewFormat();

                //YUV formats require more conversion
                if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
                    int w = parameters.getPreviewSize().width;
                    int h = parameters.getPreviewSize().height;

                    // Get the YuV image
                    YuvImage yuv_image = new YuvImage(data, format, w, h, null);
                    // Convert YuV to Jpeg
                    Rect rect = new Rect(0, 0, w, h);
                    ByteArrayOutputStream output_stream = new ByteArrayOutputStream();

                    yuv_image.compressToJpeg(rect, 10, output_stream);
                    byte[] byt = output_stream.toByteArray();

                    FileOutputStream outStream = null;
                    try {
                        outStream = new FileOutputStream(String.format(
                                "/sdcard/bb%d.jpg", System.currentTimeMillis() / 1000));

                        outStream.write(byt);
                        outStream.close();


                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {

                    }

                }

            }
        });

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setDisplayOrientation(90);
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();


        } catch (IOException e) {
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }

}

person Snoople    schedule 27.08.2013    source แหล่งที่มา


คำตอบ (2)


ขั้นแรก โปรดทราบว่า Camera.Parameters ช่วยให้คุณสามารถตั้งค่าเฟรมได้ อัตราด้วย setPreviewFrameRate ค่าต้องอยู่ในช่วงที่อธิบายโดย getPreviewFpsRange

ประการที่สอง การจัดการเฟรมแสดงตัวอย่างใน byte[] จะจำกัดอัตราเฟรมของคุณอย่างรุนแรง เนื่องจากปริมาณข้อมูลที่ต้องคัดลอก หากคุณต้องการเขียนข้อมูล YUV ฟูลเฟรมที่ยังไม่ได้แก้ไขลงดิสก์ แสดงว่าคุณไม่มีทางเลือกในขณะนี้ หากคุณสามารถรับมือกับปัญหาการบีบอัดข้อมูลได้ และคุณมี Android 4.3 ขึ้นไป คุณก็สามารถบันทึกข้อมูลเป็นวิดีโอ MPEG แล้วอ่านเฟรมกลับมาในภายหลังได้ ดูตัวอย่างโค้ดจาก CameraToMpegTest.java บน หน้านี้

การหมุนภาพ 90 หรือ 180 องศาเป็นการเขียนโค้ดที่ตรงไปตรงมา คลาส Bitmap สามารถทำได้หากคุณไม่ต้องการเขียนเอง

person fadden    schedule 27.08.2013

setPreviewCallback() เป็นวิธีที่ง่ายแต่มีประสิทธิภาพน้อยกว่าในการขอเฟรมแสดงตัวอย่าง ปัญหาหลักคือเฟรมเวิร์กอาจยุ่งมากในการจัดสรร byte[] ชิ้นที่จะเติม และผู้รวบรวมขยะอาจใช้ราคาสูง วิธีที่ต้องการคือการใช้ setPreviewCallbackWithBuffer() แต่ถึงกระนั้นก็ไม่ได้รับประกันอัตราเฟรมที่ต้องการ ดังที่เห็นใน จะรับข้อมูลตัวอย่างดิบจากวัตถุกล้องอย่างน้อย 15 เฟรมต่อวินาทีใน Android ได้อย่างไร

person Alex Cohn    schedule 02.01.2014