我正在嘗試開發一種可以用相機掃描護照頁面的掃描儀。如何使用OpenCV檢測Passport頁面的界限?
我想裁掉的標記部分。
我已經編寫了使用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;
}
}
}
此代碼適用於單頁文檔,即ID卡,信用卡。哪裏有4個可區分的邊緣。
但不適用於護照,因爲最高優勢不如其獨特。
輸入將從Android上的相機拍攝。任何想法如何檢測護照頁面?我正在使用OpenCV 3.1。
您能否提供有關拍攝條件的任何信息:光線條件(特別是在光源方向變得更暗或消失的頂部邊緣),拍攝角度(相機與護照是否垂直),那麼各種其他國家的護照(美國的旗幟從一頁傳到另一頁)呢,你將使用的背景是什麼?捕獲角度將很困難,因爲您可能不會選擇將護照平放在地面上(否則您的手會擋住護照)。請問這個問題的理由:您的圖片不是測試圖片,而是從谷歌中挑選出來的? – saurabheights
@saurabheights掃描儀應該在android/ios手機上使用。所以相機質量應該是標準智能手機相機至少500萬像素的分辨率。假設照明條件足夠好(不需要特別設置)。相機可能不完全垂直於護照,但應該靠近。背景應該與護照背景不同(較深)。它的作用是將護照儘可能平放在地面上。是的,圖片是從谷歌採取的,但解決方案應該與這些作爲基礎測試案例。 – Mehedi
我的確有一些初步的想法,比如使用Canny&Hough,並配以護照尺寸。考慮Hough變換中的垂直/接近垂直線,並對水平線做同樣的處理。水平邊緣和垂直邊緣的透視變換應該爲你提供一個矩形圖像。這個維度將有助於從護照頂端的問題。最後的聚合應該做最後的任務。背景和護照之間的顏色分割(淺色和通常居中)也可能有所幫助,但由於各個國家的護照之間存在差異,因此可能會出現錯誤。 – saurabheights