Добрый день всем.
Есть следующая проблема. Есть изображение, как правило оно выглядит как то так:
На этом изображении надо найти и прочитать коды DataMatrix, это те, кототрые в черных кругах. Я искал уже готовое опенсорсное решение. Были найдены следующие варианты:
- Zxing, но она работает только если код отцентрирован и правильно повернут
- Dmtx, у меня не получилось ее скомпилировать. Я создавал вопрос по этому поводу, но к сожалению у меня ничего не вышло.
Пoэтому было решено написать собственный велосипед. Была взята Java и openCV.
Идея такая, найти коды, узнать на какой угол они повернуты, повернуть их и скормить библиотеке Zxing.
Я сделал следующее.
Сначала нахожу круги, это более менее работает:
Те области, которые попали в круги я вырезаю. При этом я беру немного больший размер круга, чем было посчитано. Это сделано что бы точно получить область с кодом. Получается что то вроде такого:
Как вы видите на изображении ясно выделяются две белые прямые:
Если их найти, то будет ясно, где находится код и на какой угол он повернут. Для этого я ищу прямые. Код такой:
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 изображение выглядит так:
Вроде все нормально, две прямые четко видны. Но после поиска прямых найдена вообще не та прямая:
Я долго игрался с параметрами и не нашел к сожалению хорошего варианта. Не подскажите куда мне еще копать, можно ли еще как то по другому найти этот код? Заранее спасибо.