java既没有找到最大矩形的轮廓,也没有通过hough变换进行角点检测
我一直在尝试检测点击图像上最大的矩形/正方形。我尝试了轮廓Android OpenCV Find Largest Square or Rectangle和霍夫变换http://opencv-code.com/tutorials/automatic-perspective-correction-for-quadrilateral-objects/
这两个作品都是从画廊中挑选出来的。但当我把从相机拍摄的图像整合起来时,大多数情况下都会失败
有谁能告诉我背后的原因吗?我错过了什么
据我所知,像camscanner这样的许多扫描应用程序都可以以超过90%的准确率完美地完成这项工作
请建议。我试了很多
供参考:
public static String houghTransform(Mat original_image ,String outFile) {
Mat imgSource = original_image;
Mat untouched = original_image.clone();
//convert the image to black and white
Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BGR2GRAY);
//apply gaussian blur to smoothen lines of dots
Imgproc.GaussianBlur(imgSource, imgSource, new Size(5, 5), 0);
//adaptive threshold thresholds the image taking an optimum value for a local neighbourhood.
//Imgproc.adaptiveThreshold(imgSource, imgSource, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 3, 1);
//convert the image to black and white does (8 bit)
Imgproc.Canny(imgSource, imgSource, 80, 100);
Mat lines = new Mat();
int threshold = 70;
int minLineSize = 20;
int lineGap = 20;
Imgproc.HoughLinesP(imgSource, lines, 1, Math.PI/180, threshold, minLineSize, lineGap);
ArrayList<Point> corners = new ArrayList<Point>();
for (int i = 0; i < lines.cols(); i++)
{
for (int j = i+1; j < lines.cols(); j++)
{
Point pt = computeIntersect(lines.get(0,i), lines.get(0,j));
if (pt.x >= 0 && pt.y >= 0)
corners.add(pt);
}
}
L.v("Points corner size: ", ""+corners.size());
if(corners.size()<4){
return "";
}
Point center = new Point(0,0);
// Get mass center
for (int i = 0; i < corners.size(); i++){
center.x += corners.get(i).x;
center.y+= corners.get(i).y;
}
center.x = (center.x / corners.size());
center.y = (center.y / corners.size());
Core.circle(untouched, center, 20, new Scalar(255, 0, 0), 5); //p1 is colored red
Core.circle(untouched, corners.get(0), 20, new Scalar(255, 0, 0), 5);
Core.circle(untouched, corners.get(1), 20, new Scalar(255, 0, 0), 5);
Core.circle(untouched, corners.get(2), 20, new Scalar(255, 0, 0), 5);
Core.circle(untouched, corners.get(3), 20, new Scalar(255, 0, 0), 5);
Highgui.imwrite(outFile, untouched);
return outFile;
}
这里是computerIntersect模块,用于检测四个角点
private static Point computeIntersect(double[] a, double[] b) {
double x1 = a[0], y1 = a[1], x2 = a[2], y2 = a[3], x3 = b[0], y3 = b[1], x4 = b[2], y4 = b[3];
double denom = ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4));
Point pt = new Point();
if (denom!=0)
{
pt.x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denom;
pt.y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denom;
return pt;
}
else
return new Point(-1, -1);
}
在这里,当我将其应用于从相机拍摄的图像时,它会返回四个以上的点
我尝试过的另一种方法是:
public static String findLargestRectangle(Mat original_image ,String outFile) {
Mat imgSource = original_image;
Mat untouched = original_image.clone();
//convert the image to black and white
Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BGR2GRAY);
//apply gaussian blur to smoothen lines of dots
Imgproc.GaussianBlur(imgSource, imgSource, new Size(5, 5), 0);
//convert the image to black and white does (8 bit)
Imgproc.Canny(imgSource, imgSource, 80, 100);
//find the contours
List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Imgproc.findContours(imgSource, contours, new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
double maxArea = -1;
int maxAreaIdx = -1;
MatOfPoint temp_contour = contours.get(0); //the largest is at the index 0 for starting point
MatOfPoint2f approxCurve = new MatOfPoint2f();
MatOfPoint2f maxCurve = new MatOfPoint2f();
List<MatOfPoint> largest_contours = new ArrayList<MatOfPoint>();
for (int idx = 0; idx < contours.size(); idx++) {
temp_contour = contours.get(idx);
double contourarea = Imgproc.contourArea(temp_contour);
//compare this contour to the previous largest contour found
if (contourarea > maxArea) {
// Imgproc.drawContours(untouched, contours, maxAreaIdx, new Scalar(0, 255, 0), 1);
//check if this contour is a square
MatOfPoint2f new_mat = new MatOfPoint2f( temp_contour.toArray() );
int contourSize = (int)temp_contour.total();
Imgproc.approxPolyDP(new_mat, approxCurve, contourSize*0.05, true);
if (approxCurve.total() == 4) {
maxCurve = approxCurve;
maxArea = contourarea;
maxAreaIdx = idx;
largest_contours.add(temp_contour);
}
}
}
Imgproc.drawContours(imgSource, contours, maxAreaIdx, new Scalar(0, 255, 0), 5); //will draw the largest square/rectangle
}
谢谢
共 (0) 个答案