Android Camera conflict between OCR and taking picture from preview

1k Views Asked by At

I am developping an android application that combine a camera review in order to take picture and at the same time i want show OCR blocktext over the preview , the application first waorked fine with only taking picture from the preview , but when i added the OCR i don't get the preview anymore (just white scrren) but the OCR is working and showing up detected caracters. i think there is a problem with the camera opened by the preview and the OCR , kind of a conflict , but i can't find it.

here is a sample of my code :

    Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
Context context;

@BindView(R.id.preview_layout)
LinearLayout previewLayout;

@BindView(R.id.border_camera)
View borderCamera;
@BindView(R.id.res_border_size)
TextView resBorderSizeTV;

private OnFragmentInteractionListener mListener;

private TextRecognizer textRecognizer;
private CameraSource cameraSource;
private TextView textBlockContent;

Camera.Size previewSizeOptimal;

public interface OnFragmentInteractionListener {
    void onFragmentInteraction(Bitmap bitmap);
}


@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setRetainInstance(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_photo, container, false);
    ButterKnife.bind(this, view);
    context = getContext();
    surfaceView = (SurfaceView) view.findViewById(R.id.camera_preview_surface);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);


    //--------------------------------------------------------------------- OCR elements -----------------------------------------------------
    textBlockContent = view.findViewById(R.id.textBlockContent);
    textRecognizer = new TextRecognizer.Builder(getActivity().getApplicationContext()).build();

    return view;
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    camera = Camera.open();

    //--------------------------------------------------------------------- OCR Process-----------------------------------------------------

    try {
        //noinspection MissingPermission
        int rc = ActivityCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.CAMERA);
        if (rc == PackageManager.PERMISSION_GRANTED) {
            if (!textRecognizer.isOperational()) {
                Log.w("MainActivity", "Detector dependencies are not yet available.");
            }
            cameraSource = new CameraSource.Builder(getActivity().getApplicationContext(), textRecognizer)
                    .setFacing(CameraSource.CAMERA_FACING_BACK)
                    .setRequestedPreviewSize(1280, 1024)
                    .setRequestedFps(2.0f)
                    .setAutoFocusEnabled(true)
                    .build();

            cameraSource.start(surfaceHolder);
        } else {
            //requestCameraPermission();
        }
    } catch (IOException ex) {
        ex.printStackTrace();
    }

    textRecognizer.setProcessor(new Detector.Processor<TextBlock>() {
        @Override
        public void release() {

        }

        @Override
        public void receiveDetections(Detector.Detections<TextBlock> detections) {
            Log.d("Main", "receiveDetections");
            final SparseArray<TextBlock> items = detections.getDetectedItems();
            if (items.size() != 0) {
                Log.d("Main", "receiveDetections : " + items.toString());
                textBlockContent.post(new Runnable() {
                    @Override
                    public void run() {
                        StringBuilder value = new StringBuilder();
                        for (int i = 0; i < items.size(); ++i) {
                            TextBlock item = items.valueAt(i);
                            value.append(item.getValue());
                            value.append("\n");
                        }
                        //update text block content to TextView
                        textBlockContent.setText(value.toString());
                    }
                });
            }

        }
    });
    //--------------------------------------------------------------------- End OCR -----------------------------------------------------
}


@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    if (previewing) {
        camera.stopPreview();
        previewing = false;
    }
    if (camera != null) {
        try {
            Camera.Parameters parameters = camera.getParameters();

            //get preview sizes
            List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();

            //find optimal - it very important
            previewSizeOptimal = getOptimalPreviewSize(previewSizes, parameters.getPictureSize().width, parameters.getPictureSize().height);
            //TODO TESSSSSSST
            //set parameters
            if (previewSizeOptimal != null) {
                parameters.setPreviewSize(previewSizeOptimal.width, previewSizeOptimal.height);
            }
            if (camera.getParameters().getFocusMode().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }
            if (camera.getParameters().getFlashMode() != null && camera.getParameters().getFlashMode().contains(Camera.Parameters.FLASH_MODE_AUTO)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
            }


            camera.setParameters(parameters);

            //rotate screen, because camera sensor usually in landscape mode
            Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            if (display.getRotation() == Surface.ROTATION_0) {
                camera.setDisplayOrientation(90);
            } else if (display.getRotation() == Surface.ROTATION_270) {
                camera.setDisplayOrientation(180);
            }
            //write some info
            int x1 = previewLayout.getWidth();
            int y1 = previewLayout.getHeight();
            int x2 = borderCamera.getWidth();
            int y2 = borderCamera.getHeight();
            String info =
                    "Preview width:" + String.valueOf(x1) + "\n" + "Preview height:" + String.valueOf(y1) + "\n" + "Border width:" + String.valueOf(x2) + "\n" + "Border height:" + String.valueOf(y2);
            resBorderSizeTV.setText(info);
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
            previewing = true;


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}


public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    if (sizes == null) return null;
    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;
    int targetHeight = h;
    // Try to find an size match aspect ratio and size
    for (Camera.Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }
    // Cannot find the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    camera.stopPreview();
    camera.release();
    camera = null;
    previewing = false;

    cameraSource.stop();
}


@OnClick(R.id.make_photo_button)
void makePhoto() {
    if (camera != null) {
        camera.takePicture(myShutterCallback, myPictureCallback_RAW, myPictureCallback_JPG);

    }
}

Camera.ShutterCallback myShutterCallback = new Camera.ShutterCallback() {
    @Override
    public void onShutter() {
    }
};
Camera.PictureCallback myPictureCallback_RAW = new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
    }
};


Camera.PictureCallback myPictureCallback_JPG = new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        Bitmap bitmapPicture = BitmapFactory.decodeByteArray(data, 0, data.length);
        Bitmap croppedBitmap = null;
        Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        if (display.getRotation() == Surface.ROTATION_0) {
            //rotate bitmap, because camera sensor usually in landscape mode
            Matrix matrix = new Matrix();
            matrix.postRotate(90);
            Bitmap rotatedBitmap = Bitmap.createBitmap(bitmapPicture, 0, 0, bitmapPicture.getWidth(), bitmapPicture.getHeight(), matrix, true);
            Log.i("onPictureTaken", "rotatedBitmap width" + rotatedBitmap.getWidth());
            Log.i("onPictureTaken", "rotatedBitmap height " + rotatedBitmap.getHeight());
            Log.i("onPictureTaken", "previewLayout.getWidth() " + previewLayout.getWidth());
            Log.i("onPictureTaken", "previewLayout.getHeight() " + previewLayout.getHeight());
            //save file
            createImageFile(rotatedBitmap);
            //calculate aspect ratio
            float koefX = (float) rotatedBitmap.getWidth() / (float) previewLayout.getWidth();
            float koefY = (float) rotatedBitmap.getHeight() / (float) previewLayout.getHeight();
            Log.i("onPictureTaken", "koefx " + koefX);
            Log.i("onPictureTaken", "koefy " + koefY);
            //get viewfinder border size and position on the screen
            int x1 = borderCamera.getLeft();
            int y1 = borderCamera.getTop();
            int x2 = borderCamera.getWidth();
            int y2 = borderCamera.getHeight();
            Log.i("onPictureTaken", "borderCamera.getWidth() " + borderCamera.getWidth());
            Log.i("onPictureTaken", "borderCamera.getHeight() " + borderCamera.getHeight());
            //TODO size 1028 * 1251
            //calculate position and size for cropping
            int cropStartX = Math.round(x1 * koefX);
            int cropStartY = Math.round(y1 * koefY);
            int cropWidthX = Math.round(x2 * koefX);
            int cropHeightY = Math.round(y2 * koefY);
            //check limits and make crop
            if (cropStartX + cropWidthX <= rotatedBitmap.getWidth() && cropStartY + cropHeightY <= rotatedBitmap.getHeight()) {
                croppedBitmap = Bitmap.createBitmap(rotatedBitmap, cropStartX, cropStartY, cropWidthX, cropHeightY);
            } else {
                croppedBitmap = null;
            }
            //save result
            if (croppedBitmap != null) {
                // Scale down to the output size
                //Bitmap scaledBitmap = Bitmap.createScaledBitmap(croppedBitmap, 1028, 1251, true);
                createImageFile(croppedBitmap);
            }

        } else if (display.getRotation() == Surface.ROTATION_270) {
            // for Landscape mode
        }
        //pass to another fragment
        if (mListener != null) {
            if (croppedBitmap != null) mListener.onFragmentInteraction(croppedBitmap);
        }
        if (camera != null) {
            camera.startPreview();
        }
    }
};


public void createImageFile(final Bitmap bitmap) {
    File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    String timeStamp = new SimpleDateFormat("MMdd_HHmmssSSS").format(new Date());
    String imageFileName = "pic_" + timeStamp + ".jpg";
    final File file = new File(path, imageFileName);
    try {
        // Make sure the Pictures directory exists.
        if (path.mkdirs()) {
            Toast.makeText(context, "Not exist :" + path.getName(), Toast.LENGTH_SHORT).show();
        }
        OutputStream os = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
        os.flush();
        os.close();
        Log.i("ExternalStorage", "Writed " + path + file.getName());
        // Tell the media scanner about the new file so that it is
        // immediately available to the user.
        MediaScannerConnection.scanFile(context, new String[]{file.toString()}, null, new MediaScannerConnection.OnScanCompletedListener() {
            public void onScanCompleted(String path, Uri uri) {
                Log.i("ExternalStorage", "Scanned " + path + ":");
                Log.i("ExternalStorage", "-> uri=" + uri);
            }
        });
        Toast.makeText(context, file.getName(), Toast.LENGTH_SHORT).show();

    } catch (Exception e) {
        // Unable to create file, likely because external storage is
        // not currently mounted.
        Log.w("ExternalStorage", "Error writing " + file, e);
    }
}
0

There are 0 best solutions below