Как эффективно применить детектор краев Canny на изображении с помощью Opencv в Android? - PullRequest
0 голосов
/ 25 января 2019

Я создаю приложение для Android для обнаружения нескольких объектов на изображении, затем обрабатываю эти объекты и сравниваю их с эталонными объектами для обнаружения аномалий.Я тестировал разные детекторы краев изображения в python, и оператор Prewitt дал мне лучший результат, как показано ниже https://i.imgur.com/4iwOx9s.png Для Android я использовал детектор краев Canny, но результат не так хорош, как Prewitt, как показано ниже https://i.imgur.com/Bax1Wxw.png Цель применения детектора контуров Canny состоит в том, чтобы сначала обнаружить самый большой контур, затем извлечь этот контур и обнаружить каждый объект, найденный в этом контуре (в моем случае это 3 объекта).

Вот код Java, который я пробовал

    Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.coffret);

    //compress bitmap
    bmp = getResizedBitmap(bmp, 500);

    Mat rgbMat = new Mat();
    Utils.bitmapToMat(bmp, rgbMat);


    Mat grayMat = new Mat();
    Mat bwMat = new Mat();

    Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);
    Imgproc.equalizeHist(grayMat, grayMat);

    //Imgproc.adaptiveThreshold(grayMat, grayMat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 15, 40);
    Imgproc.Canny(grayMat, bwMat, 50, 200, 3, false);

    //find largest contour
    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Imgproc.findContours(bwMat, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE);

        double maxArea = -1;
        int maxAreaIdx = -1;
        if (contours.size() > 0) {
            MatOfPoint temp_contour = contours.get(0); //the largest is at the index 0 for starting point
            MatOfPoint2f approxCurve = new MatOfPoint2f();
            Mat largest_contour = contours.get(0);
            List<MatOfPoint> largest_contours = new ArrayList<MatOfPoint>();
            for (int idx = 0; idx < contours.size(); idx++) {
                temp_contour = contours.get(idx);
                double contourarea = Imgproc.contourArea(temp_contour);
                //compare this contour to the previous largest contour found
                if (contourarea > maxArea) {
                    //check if this contour is a square
                    MatOfPoint2f new_mat = new MatOfPoint2f( temp_contour.toArray() );
                    int contourSize = (int)temp_contour.total();
                    Imgproc.approxPolyDP(new_mat, approxCurve, contourSize*0.05, true);
                    if (approxCurve.total() == 4) {
                        maxArea = contourarea;
                        maxAreaIdx = idx;
                        largest_contours.add(temp_contour);
                        largest_contour = temp_contour;
                    }
                }
            }

            if (largest_contours.size() >= 1) {
                MatOfPoint temp_largest = largest_contours.get(largest_contours.size()-1);
                largest_contours = new ArrayList<MatOfPoint>();
                largest_contours.add(temp_largest);
                Imgproc.cvtColor(bwMat, bwMat, Imgproc.COLOR_BayerBG2RGB);
                Imgproc.drawContours(bwMat, largest_contours, -1, new Scalar(0, 255, 0), 1);
            }
        }


    Utils.matToBitmap(bwMat, bmp);

    Matrix matrix = new Matrix();
    matrix.postRotate(180);

    bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);

    imgView.setImageBitmap(bmp);

Как вы можете заметить, с помощью оператора Prewitt текст становится четким, а контуры более четкими.Я думаю, что я не применяю Canny правильно, поэтому самый большой контур не обнаружен.Что я делаю не так?

Редактировать: вот оригинальное изображение https://i.imgur.com/BtyZOvj.jpg

1 Ответ

0 голосов
/ 25 января 2019

Кажется, вы правильно используете детектор краев Canny. Однако иногда может оказаться целесообразным определить правильные минимальные и максимальные значения для пороговых границ.

Может быть, интервал, который вы используете (то есть, от 50 до 200), велик для вашей цели. Вы можете попробовать более высокие минимальные и максимальные значения с короткими интервалами, например, от 175 до 200.

Поскольку изображение становится сложным, вам необходимо особенно внимательно следить за этими параметрами. Иногда для разных разделов вашего изображения требуются разные минимальные и максимальные пороги. Взгляните на эту ссылку, она содержит приличное объяснение о Улучшение обнаружения канни края . В конце этой страницы есть объяснение того, как определить двухпороговое значение .

...