【发布时间】:2020-09-26 22:02:57
【问题描述】:
我必须构建一个程序,该程序采用倾斜形式(已扫描的图像)进行图像处理。第一步是消除偏斜。我成功地获得了图像的轮廓,我正在尝试做一个four_point_transform,如这篇文章Remove top section of image above border line to detect text document 中所述。但是,由于以下原因,我的代码失败了:
错误
java.lang.RuntimeException: OpenCV(4.4.0) C:\projects\javacpp-presets\opencv\cppbuild\windows-x86_64\opencv-4.4.0\modules\imgproc\src\imgwarp.cpp:3391: error: (-215:Assertion failed) src.checkVector(2, CV_32F) == 4 && dst.checkVector(2, CV_32F) == 4 in function 'cv::getPerspectiveTransform
代码
protected static void fixSkeweness(Mat mat){
Mat mask = new Mat();
Mat gray = new Mat();
Mat denoised = new Mat();
Mat bin = new Mat();
Mat hierarchy = new Mat();
MatVector contours = new MatVector();
cvtColor(mat, gray, COLOR_BGR2GRAY);
//Normalize
GaussianBlur(gray, denoised, new Size(5, 5), 0);
threshold(denoised, mask, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
normalize(gray, gray, 0, 255, NORM_MINMAX, -1, mask);
// Convert image to binary
threshold(gray, bin, 150, 255, THRESH_BINARY);
// Find contours
findContours(bin, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE);
long contourCount = contours.size();
System.out.println("Countour count " + contourCount);
double maxArea = 0;
int maxAreaId = 0;
for (int i = 0; i < contourCount; ++i) {
// Calculate the area of each contour
Mat contour = contours.get(i);
double area = contourArea(contour);
if(area > maxArea){
maxAreaId = i;
maxArea = area;
}
}
Double peri = arcLength(contours.get(maxAreaId), true);
Mat newcontour = new Mat();
approxPolyDP(contours.get(maxAreaId), newcontour,0.02 * peri, true);
Mat result = new Mat();
getPerspectiveTransform(newcontour.reshape(4,2), result);
imwrite("src/test/resources/isDataPage/fourPointTransform.jpg", result);
}
失败的代码行是:
getPerspectiveTransform(newcontour.reshape(4,2), result);
请问我可以得到一些帮助吗?
示例图片:
根据建议答案的工作代码
protected static Mat findBiggestContour(Mat mat){
Mat mask = new Mat();
Mat gray = new Mat();
Mat denoised = new Mat();
Mat bin = new Mat();
Mat hierarchy = new Mat();
MatVector contours = new MatVector();
//Pre-process image
cvtColor(mat, gray, COLOR_BGR2GRAY);
threshold(gray, bin, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);
findContours(bin, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
double maxArea = 0;
int maxAreaId = 0;
for (int i = 0; i < contours.size(); ++i) {
// Calculate the area of each contour
Mat contour = contours.get(i);
double area = contourArea(contour);
if(area > 5000 && i!=0){
maxAreaId = i;
maxArea = area;
}
}
//Get Min Area Rect and inverse it
RotatedRect rect = minAreaRect(contours.get(maxAreaId));
float newAngle = rect.angle();
if (rect.angle() < 45){
newAngle = newAngle + 90;
}
RotatedRect angle =rect.angle( newAngle);
int h = mat.size().height();
int w = mat.size().width();
int centerW = w/2;
int centerH = h/2;
//find rotation matrix and apply it woohoo
Point2f center = new Point2f(centerW, centerH);
Mat m = getRotationMatrix2D(center, angle.angle(), 1.0);
Mat rotated = new Mat();
warpAffine(mat,rotated,m, new Size(w, h),INTER_CUBIC,BORDER_REPLICATE,new Scalar(10,10));
imwrite("src/test/resources/tmp2/rotrated.png",rotated);
return rotated;
}
【问题讨论】:
-
OpenCV
getPerspectiveTransform()在您尝试使用它时不起作用。第一个参数是 4 个 src(当前)点的数组,第二个是 src 点应该在的 4 个点的数组。该方法返回您要传递给wrapPerspective()的变换矩阵。在此处查看用法:stackoverflow.com/a/45163886/9152984 -
谢谢你,我修好了,但我没有输出,虽然这本身很糟糕,但我意识到我期望得到的轮廓没有被识别,因此我不得不退后一步检测更好的轮廓。