使用opencv进行文档轮廓检测

时间:2016-09-15 19:32:06

标签: android opencv image-processing android-camera yuv

我正在尝试渲染相机预览帧上的最大轮廓。这是我的代码:

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        previewSize = cameraConfigUtil.cameraInstance.getParameters().getPreviewSize();
        Mat srcMat = new Mat(previewSize.height, previewSize.width, CvType.CV_8UC3);
        srcMat.put(0, 0, data);
        rect = ImageCorrection.getLargestContour(data, previewSize.height, previewSize.width);
        android.graphics.Rect rectangle = new android.graphics.Rect();
        rectangle.left = rect.x;
        rectangle.top = rect.y;
        rectangle.right = rect.x + rect.width;
        rectangle.bottom = rect.y + rect.height;
        mOverlay.clear();
        BarcodeGraphic graphic = new BarcodeGraphic(mOverlay);
        mOverlay.add(graphic);
        graphic.updateItem(rectangle);
        Imgproc.rectangle(srcMat, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(255, 0, 0, 255), 3);
        Utils.matToBitmap(srcMat, bitmap);
    }

它会检测轮廓但是当我将其添加到叠加层时,框不会放在文档上,并且边界矩形看起来更小。我正在使用预览框架中的原始数据。我错过了什么?基本上,检测到的最大轮廓与实际预览尺寸无关。

 public static Rect getLargestContour(byte[] data, int height, int width) {
        Mat srcMat = new Mat(height, width, CvType.CV_8UC3);
        srcMat.put(0, 0, data);
        Mat imgSource = new Mat(srcMat.size(), CvType.CV_8UC1);
        Imgproc.cvtColor(srcMat, imgSource, Imgproc.COLOR_RGB2GRAY, 4);
        Imgproc.GaussianBlur(imgSource, imgSource, new org.opencv.core.Size(5, 5), 0);

        Imgproc.Canny(imgSource, imgSource, 50, 50);

        List<MatOfPoint> contours = new ArrayList<>();
        Imgproc.findContours(imgSource, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
        Imgproc.cvtColor(imgSource, srcMat, Imgproc.COLOR_GRAY2RGB, 4);

        double maxArea = -1;
        Log.d("size", Integer.toString(contours.size()));
        MatOfPoint temp_contour;
        MatOfPoint2f approxCurve = new MatOfPoint2f();

        for (MatOfPoint contour : contours) {
            double contourarea = Imgproc.contourArea(contour);
            if (contourarea > 0
                    && contourarea > maxArea) {
                //check if this contour is a square
                MatOfPoint2f new_mat = new MatOfPoint2f(contour.toArray());
                int contourSize = (int) contour.total();
                MatOfPoint2f approxCurve_temp = new MatOfPoint2f();
                Imgproc.approxPolyDP(new_mat, approxCurve_temp, contourSize * 0.05, true);
                if (approxCurve_temp.total() == 4) {
                    maxArea = contourarea;
                    approxCurve = approxCurve_temp;
                }
            }
        }

        MatOfPoint points = new MatOfPoint(approxCurve.toArray());

        return Imgproc.boundingRect(points);
    }

enter image description here

这是opencv正在考虑的图像尺寸。

enter image description here

1 个答案:

答案 0 :(得分:1)

所以终于找到了问题:  在这里

 Mat srcMat = new Mat(height, width, CvType.CV_8UC3);
 srcMat.put(0, 0, data);

我将YUV类型的数据放在一个CV_8U3的Mat中。它应该是CV_8U1。

 Mat srcMat = new Mat(height, width, CvType.CV_8UC1);
 srcMat.put(0, 0, data);

我们不需要将其转换为GRAYSCALE:

 Mat imgSource = new Mat(srcMat.size(), CvType.CV_8UC1);
 Imgproc.cvtColor(srcMat, imgSource, Imgproc.COLOR_RGB2GRAY, 4);