Подтвердить что ты не робот

Как выполнить автоматическую обрезку для документа Распознать изображение с помощью камеры?

Я хочу сделать приложение, такое как сканер для обрезки документа.

Но мне нужна такая же функциональность, как мои два изображения.

Первые изображения показывают изображение, снятое камерой.

enter image description here

Второе изображение распознает часть захваченного изображения, подобное этому.

enter image description here

Я все больше и больше изучаю, но не получаю ни одного из них, поэтому я спрашиваю, может ли кто-нибудь это сказать мне.

Спасибо

4b9b3361

Ответ 2

Я предполагаю, что ваша проблема заключается в обнаружении объекта для сканирования.

Механизмы обнаружения объектов, такие как сопоставление образцов или обнаружение признаков, не приведут к результатам, которые вы ищете, так как вы не знаете, что именно сканирует объект.

В основном вы ищете прямоугольный объект на картинке.

Базовый подход к этому может быть следующим:

  • Запустите на изображении canny edge detector. Это может помочь немного размыть изображение перед этим. Края объекта должны быть хорошо видны.

  • Теперь вы хотите сделать преобразование Hough, чтобы найти строки на картинке.

  • Найдите линии с углом около 90 градусов друг от друга. Проблема заключалась бы в поиске правильных. Возможно, достаточно использовать линии, наиболее близкие к кадру изображения, которые достаточно параллельны им.

  • Найдите пересекающиеся точки для определения ребер вашего объекта.

По крайней мере, это должно дать вам подсказку, где можно продолжить исследования.

В качестве дополнительных шагов в таком приложении вам нужно будет вычислить проекцию точек и выполнить аффинное преобразование объекта.

Надеюсь, это поможет.

После написания всего этого я нашел этот пост. Он должен помочь вам.

Поскольку мой ответ нацелен на OpenCV, вам нужно использовать библиотеку OpenCV. Для этого вам необходимо установить Android Native Development Kit (NDK). Есть несколько хороших руководств по использованию OpenCV на Android на странице OpenCV для Android.

Следует иметь в виду, что почти каждая функция оболочки Java вызывает собственный метод. Это стоит много времени. Таким образом, вы хотите сделать как можно больше в своем родном коде, прежде чем возвращать результаты в часть Java.

Ответ 3

Я знаю, что слишком поздно ответить, но кому-то это может быть полезно.

Попробуйте использовать следующий код.

@Override
protected void onDraw(Canvas canvas) {

  super.onDraw(canvas);
  path = new Path();

  path.moveTo(x1, y1);        // this should set the start point right

  //path.lineTo(x1, y1);    <-- this line should be drawn at the end of     course,sorry
  path.lineTo(x2, y2);
  path.lineTo(x3, y3);
  path.lineTo(x4, y4);
  path.lineTo(x1, y1); 
  canvas.drawPath(path, currentPaint);

}

Ответ 4

Я создал репозиторий git с кодом для встроенной поддержки, который обрезает изображение по правильному пути, найдите его: link.

Не стесняйтесь редактировать код, если придумаете лучшее решение.

Ответ 5

Пропустите изображение в этом методе:

       void findSquares(Mat image, List<MatOfPoint> squares) {
    int N = 10;

    squares.clear();

    Mat smallerImg = new Mat(new Size(image.width() / 2, image.height() / 2), image.type());

    Mat gray = new Mat(image.size(), image.type());

    Mat gray0 = new Mat(image.size(), CvType.CV_8U);

    // down-scale and upscale the image to filter out the noise
    Imgproc.pyrDown(image, smallerImg, smallerImg.size());
    Imgproc.pyrUp(smallerImg, image, image.size());
    // find squares in every color plane of the image
    Outer:
    for (int c = 0; c < 3; c++) {

        extractChannel(image, gray, c);

        // try several threshold levels
        Inner:
        for (int l = 1; l < N; l++) {

            Imgproc.threshold(gray, gray0, (l + 1) * 255 / N, 255, Imgproc.THRESH_BINARY);


            List<MatOfPoint> contours = new ArrayList<MatOfPoint>();

            // find contours and store them all as a list
            Imgproc.findContours(gray0, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

            MatOfPoint approx = new MatOfPoint();

            // test each contour
            for (int i = 0; i < contours.size(); i++) {

                approx = approxPolyDP(contours.get(i), Imgproc.arcLength(new MatOfPoint2f(contours.get(i).toArray()), true) * 0.02, true);

                // square contours should have 4 vertices after approximation
                // relatively large area (to filter out noisy contours)
                // and be convex.
                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                double area = Imgproc.contourArea(approx);

                if (area > 5000) {

                    if (approx.toArray().length == 4 &&
                            Math.abs(Imgproc.contourArea(approx)) > 1000 &&
                            Imgproc.isContourConvex(approx)) {

                        double maxCosine = 0;
                        Rect bitmap_rect = null;
                        for (int j = 2; j < 5; j++) {
                            // find the maximum cosine of the angle between joint edges
                            double cosine = Math.abs(angle(approx.toArray()[j % 4], approx.toArray()[j - 2], approx.toArray()[j - 1]));
                            maxCosine = Math.max(maxCosine, cosine);
                            bitmap_rect = new Rect(approx.toArray()[j % 4], approx.toArray()[j - 2]);

                        }

                        // if cosines of all angles are small
                        // (all angles are ~90 degree) then write quandrange
                        // vertices to resultant sequence
                        if (maxCosine < 0.3)
                            squares.add(approx);

                    }
                }
            }
        }
    }
}

В этом методе вы получаете четыре точки документа, после чего вы можете вырезать это изображение, используя метод ниже:

      public Bitmap warpDisplayImage(Mat inputMat) {
    List<Point> newClockVisePoints = new ArrayList<>();

    int resultWidth = inputMat.width();
    int resultHeight = inputMat.height();

    Mat startM = Converters.vector_Point2f_to_Mat(orderRectCorners(Previes method four poit list(like : List<Point> points)));

    Point ocvPOut4 = new Point(0, 0);
    Point ocvPOut1 = new Point(0, resultHeight);
    Point ocvPOut2 = new Point(resultWidth, resultHeight);
    Point ocvPOut3 = new Point(resultWidth, 0);



        ocvPOut3 = new Point(0, 0);
        ocvPOut4 = new Point(0, resultHeight);
        ocvPOut1 = new Point(resultWidth, resultHeight);
        ocvPOut2 = new Point(resultWidth, 0);
    }

    Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC4);

    List<Point> dest = new ArrayList<Point>();
    dest.add(ocvPOut3);
    dest.add(ocvPOut2);
    dest.add(ocvPOut1);
    dest.add(ocvPOut4);


    Mat endM = Converters.vector_Point2f_to_Mat(dest);

    Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM);

    Imgproc.warpPerspective(inputMat, outputMat, perspectiveTransform, new Size(resultWidth, resultHeight), Imgproc.INTER_CUBIC);


    Bitmap descBitmap = Bitmap.createBitmap(outputMat.cols(), outputMat.rows(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(outputMat, descBitmap);



    return descBitmap;
}