Я пытаюсь разработать сканер, который может сканировать страницу паспорта с помощью камеры.
Так со страницы паспорта, как это:
Я хотел бы вырезать отмеченную часть.
Я написал код для обнаружения края с использованием OpenCV, который находит контуры и затем аппроксимирует самый большой четырехугольник. Наконец, он выполняет преобразование перспективы в 4 точки, чтобы получить вид сверху на изображение. Код обнаружения края выглядит следующим образом:
public static List<MatOfPoint> findContours(Mat src){
Mat img = src.clone();
src.release();
//find contours
double ratio = getScaleRatio(img.size());
int width = (int) (img.size().width / ratio);
int height = (int) (img.size().height / ratio);
Size newSize = new Size(width, height);
Mat resizedImg = new Mat(newSize, CvType.CV_8UC4);
Imgproc.resize(img, resizedImg, newSize);
Imgproc.medianBlur(resizedImg, resizedImg, 5);
Mat cannedImg = new Mat(newSize, CvType.CV_8UC1);
Imgproc.Canny(resizedImg, cannedImg, 70, 200, 3, true);
resizedImg.release();
Imgproc.threshold(cannedImg, cannedImg, 200, 255, Imgproc.THRESH_OTSU);
Mat dilatedImg = new Mat(newSize, CvType.CV_8UC1);
Mat morph = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));
Imgproc.dilate(cannedImg, dilatedImg, morph, new Point(-1, -1), 2, 1, new Scalar(1));
cannedImg.release();
morph.release();
ArrayList<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(dilatedImg, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
hierarchy.release();
Log.d(TAG, "contours found: " + contours.size());
Collections.sort(contours, new Comparator<MatOfPoint>() {
@Override
public int compare(MatOfPoint o1, MatOfPoint o2) {
return Double.valueOf(Imgproc.contourArea(o2)).compareTo(Imgproc.contourArea(o1));
}
});
return contours;
}
for(MatOfPoint contour:contours){
MatOfPoint2f mat = new MatOfPoint2f(contour.toArray());
double peri = Imgproc.arcLength(mat, true);
MatOfPoint2f approx = new MatOfPoint2f();
Imgproc.approxPolyDP(mat, approx, 0.02 * peri, true);
Point[] points = approx.toArray();
Log.d("SCANNER", "approx size " + points.length);
if (points.length == 4) {
Point[] spoints = CVProcessor.sortPoints(points);
if (CVProcessor.insideArea(spoints, newSize)) {
rectContour = contour;
foundPoints = spoints;
break;
}
}
}
этот код работает для одностраничных документов, т. е. удостоверений личности, кредитных карт. Где есть 4 различимых края.
Но не работает для паспортов, так как верхний край не так отличителен.
Входные данные будут взяты с камеры на Android. Любая идея, как я могу обнаружить страницу паспорта? Я использую OpenCV 3.1.
Вот несколько примеров входных данных (полученных из поиска картинок Google):
Было бы возможно извлечь страницу, если вы можете найти Машиносчитываемая зона (MRZ) паспорта (регион выделен красным на изображении ниже). Как правило, существует очень хороший контраст между МСЗ и фоном, поэтому его можно обнаружить с помощью метода градиента или MSERs.
Предполагая, что есть стандартный шаблон (то есть, пропорции для страницы, MRZ, смещения для полей и т. Д.), В соответствии с которым готовится паспорт, как только вы найдете MRZ, легко найти границы страницы и другие поля. такие как фотография человека, как показано на изображении шаблона ниже, где MRZ выделена красным, а граница страницы — зеленым. Это предполагает, что нет никакого искажения перспективы. Если есть такие искажения, сначала вы должны исправить это, а затем применить шаблон. Вы можете использовать саму MRZ для исправления искажения, поскольку вы знаете соотношение сторон региона MRZ.
Шаблон подготовлен из образ.
Проверьте Вот для очень простой реализации этого шаблона на основе извлечения полей из паспорта. Он не будет работать для ваших изображений и потребует много настроек параметров, поэтому я не рекомендую использовать его сразу. Я имею в виду, чтобы передать идею извлечения на основе шаблонов и других методов предварительной обработки.
Однако, если паспорт изогнут, как на изображении ниже (вы можете видеть, что граница MRZ не может быть прослежена с помощью прямых линий), трудно исправить искажение.
Наконец, если вы используете изображения с высоким разрешением, было бы неплохо уменьшить выборку и обработать их, как это было бы быстрее во встроенной системе. Как только вы найдете MRZ по уменьшенному изображению, вы можете использовать изображение в высоком разрешении, чтобы уточнить углы.
Других решений пока нет …