【发布时间】:2018-03-26 10:06:25
【问题描述】:
我正在尝试检测卡片并对图像进行透视。我已经成功获得了卡片的轮廓。但是我在如何获取顶点(在图像中显示为蓝点)作为 getPerspectiveTransform 函数的输入时遇到了困难。实际上,我已经在静态图像上使用简单的算法完成了它。但是,它不适用于实时帧,尤其是在卡片旋转时。有没有什么简单而健壮的方法,无论卡片的方向如何,都可以得到卡片的四个顶点?
MatOfPoint2f curve = new MatOfPoint2f(matched.toArray());
double perimeter = Imgproc.arcLength(curve, true);
MatOfPoint2f approxCurve2f = new MatOfPoint2f();
Imgproc.approxPolyDP(curve, approxCurve2f, 0.003 * perimeter, true);
Mat temp = new Mat(src.rows(),src.cols(),CvType.CV_8UC1);
Imgproc.drawContours(temp, cnt, -1, new Scalar(255,255,255));
Moments moment = Imgproc.moments(matched);
Point centroid = new Point(moment.m10/moment.m00, moment.m01/moment.m00);
MatOfPoint approxCurve = new MatOfPoint();
approxCurve2f.convertTo(approxCurve, CvType.CV_32S);
List<Point> corners = Util.toPointList(approxCurve);
//group points that near each other
List<List<Point>> grouping = Util.cornerPointGrouping(corners, 50);
if(grouping.size()!=4)
{
return temp;
}
Mat before = new Mat(1,4, CvType.CV_32FC2);
Mat after = new Mat(1,4, CvType.CV_32FC2);
Util.generateTransformationParams(grouping, centroid, before, after);
Mat transformMat = Imgproc.getPerspectiveTransform(before, after);
Mat out = new Mat();
Size dsize = new Size(src.width(), src.height());
Imgproc.warpPerspective(src, out, transformMat, dsize);
public static void generateTransformationParams(List<List<Point>> grouping,
Point centroid, Mat before, Mat after)
{
Point topLeft=new Point(), topRight=new Point(),
btmLeft=new Point(), btmRight=new Point();
for(List<Point> list: grouping)
{
List<Point> ySorted = new ArrayList<>(list);
Collections.sort(list, new xComparator());
Collections.sort(ySorted, new yComparator());
if(list.get(0).y<centroid.y) //top
{
if(list.get(0).x<centroid.x) //left
{
topLeft = new Point(list.get(0).x,ySorted.get(0).y);
}
else //right
{
topRight = new Point(list.get(list.size()-1).x,ySorted.get(0).y);
}
}
else //bottom
{
if(list.get(0).x<centroid.x) //left
{
btmLeft = new Point(list.get(0).x,ySorted.get(list.size()-1).y);
}
else //right
{
btmRight = new Point(list.get(list.size()-1).x,ySorted.get(list.size()-1).y);
}
}
}
//btmLeft as reference
before.put(0, 0, topLeft.x, topLeft.y, topRight.x, topRight.y,
btmRight.x, btmRight.y, btmLeft.x, btmLeft.y);
double width = Util.getLength(btmLeft, btmRight);
double height = width/creditCardRatio;
after.put(0, 0, btmLeft.x, btmLeft.y-height, btmLeft.x+width, btmLeft.y-height,
btmLeft.x+width, btmLeft.y, btmLeft.x, btmLeft.y);
}
【问题讨论】:
-
这可能会有所帮助pyimagesearch.com/2014/08/25/…
-
@Gopiraj 我不明白第 5 步和第 6 步
-
近似轮廓后,您将在轮廓上以 4 个或更多点结束,使用这些点形成一条线。例如 line1 = (points[0], points[1]), ... lineN = (points[N], points[0])。求直线的长度 (norm(points[0]-points[1]))。根据长度对行进行排序。获取最大的 4 行和这些行中的 find intersection points。这些线的交点将是顶点