27

这个问题已经被问过了,但我还是不明白。我通过调用cv::findHomography一组点来获得一个单应矩阵。我需要检查它是否相关。
所提出的方法是计算内点的最大重投影误差并将其与阈值进行比较。但是经过这样的过滤后,我不断得到疯狂的变换,对象边界框几乎变成一条直线或一些奇怪的非凸四边形,带有自相交等。
可以使用哪些约束来检查单应矩阵本身是否足够?

4

2 回答 2

38

你的问题是数学问题。给定一个 3x3 的矩阵,决定它是否代表一个好的刚性变换。很难定义什么是“好”,但这里有一些线索可以帮助你

  1. 单应性应保持多边形点的方向。设计一个简单的测试。点 (0,0), (imwidth,0), (width,height), (0,height) 表示具有顺时针排列点的四边形。在这些点上应用单应性,看看它们是否仍然是顺时针排列的,如果它们变成逆时针方向,你的单应性正在翻转(镜像)有时仍然可以的图像。但是,如果你的点是乱序的,那么你就有一个“糟糕的单应性”
  2. 单应性不会过多地改变对象的比例。例如,如果您希望它将图像缩小或放大 X 倍,只需检查此规则。用单应性变换4个点(0,0),(imwidth,0),(width-1,height),(0,height)并计算四边形的面积(opencv计算多边形面积的方法)如果比率面积太大(或太小),您可能有错误。
  3. 良好的单应性通常使用较低的透视值。通常,如果图像的大小为 ~1000x1000 像素,则这些值应为 ~0.005-0.001。高透视会导致巨大的失真,这可能是一个错误。如果您不知道这些值的位置,请阅读我的帖子: 尝试理解仿射变换 。它解释了仿射变换数学,其他 2 个值是透视参数。

我认为如果您检查上述 3 个条件(条件 2 是最重要的),您将能够检测到大部分问题。祝你好运

于 2013-02-19T19:02:40.347 回答
1

编辑:这个答案与问题无关,但讨论可能对像我一样尝试使用匹配结果进行识别的人有所帮助!

这可能会帮助某人:

Point2f[] objCorners = { new Point2f(0, 0),
    new Point2f(img1.Cols, 0),
    new Point2f(img1.Cols, img1.Rows),
    new Point2f(0, img1.Rows) };

Point2d[] sceneCorners = MyPerspectiveTransform3(objCorners, homography);
double marginH = img2.Width * 0.1d;
double marginV = img2.Height * 0.1d;
bool homographyOK = isInside(-marginH, -marginV, img2.Width + marginH, img2.Height + marginV, sceneCorners);
if (homographyOK)
    for (int i = 1; i < sceneCorners.Length; i++)
        if (sceneCorners[i - 1].DistanceTo(sceneCorners[i]) < 1)
        {
            homographyOK = false;
            break;
        }
if (homographyOK)
    homographyOK = isConvex(sceneCorners);
if (homographyOK)
    homographyOK = minAngleCheck(sceneCorners, 20d);




     private static bool isInside(dynamic minX, dynamic minY, dynamic maxX, dynamic maxY, dynamic coors)
        {
            foreach (var c in coors)
                if ((c.X < minX) || (c.Y < minY) || (c.X > maxX) || (c.Y > maxY))
                    return false;
            return true;
        }      
        private static bool isLeft(dynamic a, dynamic b, dynamic c)
        {
            return ((b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X)) > 0;
        }
        private static bool isConvex<T>(IEnumerable<T> points)
        {
            var lst = points.ToList();
            if (lst.Count > 2)
            {
                bool left = isLeft(lst[0], lst[1], lst[2]);
                lst.Add(lst.First());
                for (int i = 3; i < lst.Count; i++)
                    if (isLeft(lst[i - 2], lst[i - 1], lst[i]) != left)
                        return false;
                return true;
            }
            else
                return false;
        }
        private static bool minAngleCheck<T>(IEnumerable<T> points, double angle_InDegrees)
        {
            //20d * Math.PI / 180d
            var lst = points.ToList();
            if (lst.Count > 2)
            {                
                lst.Add(lst.First());
                for (int i = 2; i < lst.Count; i++)
                {
                    double a1 = angleInDegrees(lst[i - 2], lst[i-1]);
                    double a2 = angleInDegrees(lst[i], lst[i - 1]);
                    double d = Math.Abs(a1 - a2) % 180d;

                    if ((d < angle_InDegrees) || ((180d - d) < angle_InDegrees))
                        return false;
                }
                return true;
            }
            else
                return false;
        }
        private static double angleInDegrees(dynamic v1, dynamic v2)
        {
            return (radianToDegree(Math.Atan2(v1.Y - v2.Y, v1.X - v2.X))) % 360d;
        }
        private static double radianToDegree(double radian)
        {
            var degree = radian * (180d / Math.PI);
            if (degree < 0d)
                degree = 360d + degree;

            return degree;
        }
        static Point2d[] MyPerspectiveTransform3(Point2f[] yourData, Mat transformationMatrix)
        {
            Point2f[] ret = Cv2.PerspectiveTransform(yourData, transformationMatrix);
            return ret.Select(point2fToPoint2d).ToArray();
        }  

在此处输入图像描述

于 2017-01-24T12:27:30.547 回答