@schroeder

Как найти обьект на изображении?

Добрый день всем.
Есть следующая проблема. Есть изображение, как правило оно выглядит как то так:
b25f664dde5a42b7ac7ce9810f36f644.bmp

На этом изображении надо найти и прочитать коды DataMatrix, это те, кототрые в черных кругах. Я искал уже готовое опенсорсное решение. Были найдены следующие варианты:

  1. Zxing, но она работает только если код отцентрирован и правильно повернут
  2. Dmtx, у меня не получилось ее скомпилировать. Я создавал вопрос по этому поводу, но к сожалению у меня ничего не вышло.


Пoэтому было решено написать собственный велосипед. Была взята Java и openCV.

Идея такая, найти коды, узнать на какой угол они повернуты, повернуть их и скормить библиотеке Zxing.
Я сделал следующее.
Сначала нахожу круги, это более менее работает:

873ef8907d834949a1c93891bd3b4698.bmp

Те области, которые попали в круги я вырезаю. При этом я беру немного больший размер круга, чем было посчитано. Это сделано что бы точно получить область с кодом. Получается что то вроде такого:
0e5b3433662b4620bf6a36b8aace22a8.bmp

Как вы видите на изображении ясно выделяются две белые прямые:
6d89c4fe9a2246358b9e371387e88a2e.bmp
Если их найти, то будет ясно, где находится код и на какой угол он повернут. Для этого я ищу прямые. Код такой:

Mat binImage = new Mat(image.rows(), image.cols(), image.type());
        Imgproc.GaussianBlur(image, binImage, new Size(5, 5), 5, 5);
        Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 5, 0);
        double iCannyLowerThreshold = 25;
        double iCannyUpperThreshold = 70;
        Imgproc.Canny(binImage, binImage, iCannyLowerThreshold, iCannyUpperThreshold);
        Highgui.imwrite("lines/cannyImage_" + counter + ".bmp", binImage);

        List<Line> result = new ArrayList<Line>();
        Mat lines = new Mat();
        int linesThreshold = 20;
        int linesMinLineSize = 35;
        int linesGap = 5;
        Imgproc.HoughLinesP(binImage, lines, 1, Math.PI / 180, linesThreshold, linesMinLineSize, linesGap);

        for (int x = 0; x < lines.cols(); x++) {
            double[] vecHoughLines = lines.get(0, x);

            if (vecHoughLines.length == 0)
                break;

            double x1 = vecHoughLines[0];
            double y1 = vecHoughLines[1];
            double x2 = vecHoughLines[2];
            double y2 = vecHoughLines[3];
            Point pt1 = new Point();
            Point pt2 = new Point();

            pt1.x = x1;
            pt1.y = y1;
            pt2.x = x2;
            pt2.y = y2;
            result.add(new Line(pt1, pt2));
            Core.line(image, pt1, pt2, new Scalar(255, 0, 0, 255), 2);
        }


К сожалению результаты не очень. После Canny изображение выглядит так:
7253d3f2a01f4daf881512f918351763.bmp
Вроде все нормально, две прямые четко видны. Но после поиска прямых найдена вообще не та прямая:
db94b0e3f0d34b07bfd42ccb7160078f.bmp

Я долго игрался с параметрами и не нашел к сожалению хорошего варианта. Не подскажите куда мне еще копать, можно ли еще как то по другому найти этот код? Заранее спасибо.
  • Вопрос задан
  • 2618 просмотров
Пригласить эксперта
Ответы на вопрос 1
sofcom
@sofcom
DevOps & IT Produce & Digital marketing
Определил круги, в кругах предполагается QR-код. Бросай этот QR-код в библиотеку работающую с этими кодами, не выравнивая, очищая все что за кругами находится
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы