我已決定捕捉到整卡而不是僅僅的代碼。通過捕獲整個卡片,可以將其轉換爲簡單的視角,然後我可以輕鬆獲得「代碼」區域。
另外我學到了很多東西。特別是關於速度。此功能在高分辨率圖像上很慢。它可能需要長達10秒的大小爲3264 X 1836
我做了什麼,以加快速度,重新調整大小由1/4
因子輸入矩陣。這使得它快了很多,並且給了我極小的精度損失。下一步是將我們找到的四邊形縮放到正常尺寸。因此,我們可以使用原始來源將四邊形轉換爲簡單的視角。
我檢測的最大區域創建的代碼是大量基於代碼,我計算器上找到。不幸的是,他們沒有像我預期的那樣工作,所以我組合了更多的代碼片段並進行了很多修改。 這是我的了:
private static double angle(Point p1, Point p2, Point p0) {
double dx1 = p1.x - p0.x;
double dy1 = p1.y - p0.y;
double dx2 = p2.x - p0.x;
double dy2 = p2.y - p0.y;
return (dx1 * dx2 + dy1 * dy2)/Math.sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2) + 1e-10);
}
private static MatOfPoint find(Mat src) throws Exception {
Mat blurred = src.clone();
Imgproc.medianBlur(src, blurred, 9);
Mat gray0 = new Mat(blurred.size(), CvType.CV_8U), gray = new Mat();
List<MatOfPoint> contours = new ArrayList<>();
List<Mat> blurredChannel = new ArrayList<>();
blurredChannel.add(blurred);
List<Mat> gray0Channel = new ArrayList<>();
gray0Channel.add(gray0);
MatOfPoint2f approxCurve;
double maxArea = 0;
int maxId = -1;
for (int c = 0; c < 3; c++) {
int ch[] = {c, 0};
Core.mixChannels(blurredChannel, gray0Channel, new MatOfInt(ch));
int thresholdLevel = 1;
for (int t = 0; t < thresholdLevel; t++) {
if (t == 0) {
Imgproc.Canny(gray0, gray, 10, 20, 3, true); // true ?
Imgproc.dilate(gray, gray, new Mat(), new Point(-1, -1), 1); // 1 ?
} else {
Imgproc.adaptiveThreshold(gray0, gray, thresholdLevel, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, (src.width() + src.height())/200, t);
}
Imgproc.findContours(gray, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
for (MatOfPoint contour : contours) {
MatOfPoint2f temp = new MatOfPoint2f(contour.toArray());
double area = Imgproc.contourArea(contour);
approxCurve = new MatOfPoint2f();
Imgproc.approxPolyDP(temp, approxCurve, Imgproc.arcLength(temp, true) * 0.02, true);
if (approxCurve.total() == 4 && area >= maxArea) {
double maxCosine = 0;
List<Point> curves = approxCurve.toList();
for (int j = 2; j < 5; j++)
{
double cosine = Math.abs(angle(curves.get(j % 4), curves.get(j - 2), curves.get(j - 1)));
maxCosine = Math.max(maxCosine, cosine);
}
if (maxCosine < 0.3) {
maxArea = area;
maxId = contours.indexOf(contour);
//contours.set(maxId, getHull(contour));
}
}
}
}
}
if (maxId >= 0) {
return contours.get(maxId);
//Imgproc.drawContours(src, contours, maxId, new Scalar(255, 0, 0, .8), 8);
}
return null;
}
你可以把它像這樣:
MathOfPoint contour = find(src);
看到這個答案的四邊形檢測從輪廓和其轉化爲一個普通的觀點: Java OpenCV deskewing a contour
我張貼的答案相關的問題,你貼在[OpenCV的論壇](http://answers.opencv.org/question/18101/java-opencv-tesseract-ocr-code-regocnition/) – tleyden
感謝@Tim驗證碼對我非常有幫助但是我不得不對你的代碼做一些修改,因爲我無法得到如何用'MatOfPoint'在圖像周圍畫一個矩形。現在它爲我工作,但我仍然面臨一個問題。有時候這會在圖像上獲得一個只有一半的矩形,或者有時它會繪製多個矩形。你能告訴我一些如何解決這個問題。 – UltimateDevil