【问题标题】:Converting OpenCV's findHomography perspective matrix to iOS' CATransform3D将 OpenCV 的 findHomography 透视矩阵转换为 iOS 的 CATransform3D
【发布时间】:2013-01-06 05:23:20
【问题描述】:

我想采用从 OpenCV 的 findHomography 函数返回的透视变换矩阵并将其(在 C++ 或 Objective-C 中)转换为 iOS 的 CATransform3D。我希望它们在准确再现核心图形方面的“扭曲”效果方面尽可能接近。示例代码将不胜感激!

来自 iOS 的 CATransform3D.h:

/* Homogeneous three-dimensional transforms. */

struct CATransform3D
{
    CGFloat m11, m12, m13, m14;
    CGFloat m21, m22, m23, m24;
    CGFloat m31, m32, m33, m34;
    CGFloat m41, m42, m43, m44;
};

类似问题:

Apply homography matrix using Core Graphics

convert an opencv affine matrix to CGAffineTransform

【问题讨论】:

    标签: ios opencv matrix perspective catransform3d


    【解决方案1】:

    根据我对文档的阅读,CATransform3D 中的m11 相当于CGAffineTransform 中的am12 相当于b 等等。

    根据您在下面的评论,我了解 OpenCV 返回的矩阵为 3x3(回想起来,这是您期望的大小)。因此,您将使用与单位矩阵等效的元素填充其他元素。根据 Hammer 的回答,您希望保留处理(通常是隐含的)同质坐标的部分,同时用标识填充其他所有内容。

    [顺便说一句:我原来的答案是错误。我已经将其编辑为正确,因为我已经发布了代码而 Hammer 没有。这篇文章被标记为社区 wiki,以反映这绝不是我的回答]

    所以我想你会想要:

    CATransform3D MatToTransform(Mat cvTransform)
    {
        CATransform3D transform;
    
        transform.m11 = cvTransform.at<float>(0, 0);
        transform.m12 = cvTransform.at<float>(1, 0);
        transform.m13 = 0.0f;
        transform.m14 = cvTransform.at<float>(2, 0);
    
        transform.m21 = cvTransform.at<float>(0, 1);
        transform.m22 = cvTransform.at<float>(1, 1);
        transform.m23 = 0.0f;
        transform.m24 = cvTransform.at<float>(2, 1);
    
        transform.m31 = 0.0f;
        transform.m32 = 0.0f;
        transform.m33 = 1.0f;
        transform.m34 = 0.0f;
    
        transform.m41 = cvTransform.at<float>(0, 2);
        transform.m42 = cvTransform.at<float>(1, 2);
        transform.m43 = 0.0f;
        transform.m44 = cvTransform.at<float>(2, 2);
    
        return transform;
    }
    

    如果您不想使用 C++,请使用 cvGetReal1D

    【讨论】:

    • 是的,但是 findHomography 返回一个 3x3 矩阵而不是 4x4
    • +1 表示行专业到列专业。出于某种原因,m11 符号总是让我感到困惑。我似乎认为排专业最好
    • 在这种情况下,用标识元素填充其他条目应该是安全的。稍等,我会更新...
    • 谢谢大家,我晚饭后试试看。
    • 我试过了,但是没有用。结果矩阵的旋转始终是 pi/2 的倍数,并且比例很大(比例和旋转竞争如 stackoverflow.com/questions/15420693/… 中所回答)
    【解决方案2】:

    免责声明

    我从未尝试过,所以请谨慎对待。

    CATransform3D 是一个 4x4 矩阵,它对 3 维齐次向量 (4x1) 进行运算以生成另一个相同类型的向量。我假设在渲染时,由 4x1 向量描述的对象将每个元素除以第 4 个元素,而第 3 个元素仅用于确定哪些对象出现在哪些对象之上。假设这是正确的......

    推理

    findHomography 返回的 3x3 矩阵对二维齐次向量进行运算。该过程可以分为 4 个步骤

    1. 单应性的第一列乘以x
    2. 单应性第二列乘以y
    3. 单应性第三列乘以1
    4. 得到的第一个和第二个向量元素除以第三个

    您需要在 4x4 向量中复制此过程,我假设结果向量中的第三个元素对您的目的没有意义。

    解决方案

    像这样构造你的矩阵(H 是你的单应矩阵)

    [H(0,0), H(0,1), 0, H(0,2),
     H(1,0), H(1,1), 0, H(1,2),
          0,      0, 1,      0
     H(2,0), H(2,1), 0, H(2,2)]
    

    这显然满足 1,2 和 3。满足 4 是因为齐次元素总是最后一个。这就是为什么“同质行”如果你不得不被撞到一条线上。第3行的1是让向量的z分量不受干扰地通过。

    以上所有内容均以行主要符号(如 openCV)完成,以尽量避免混淆。您可以查看 Tommy 的答案以了解转换为列专业的外观(您基本上只是转置它)。但是请注意,目前汤米和我在如何构建矩阵方面存在分歧。

    【讨论】:

    • 我实际上认为我们不再存在分歧,而且我明确认为你是对的。我已经更新了我的答案,但老实说,如果我给出的代码是正确的,那么我认为你应该得到勾选。提供了一些复制和粘贴的东西,使关于行/列专业的观点感觉不如指出计算机图形中的 2d 坐标通常对于 (x, y, 1) 和 3d 对于 (x, y) 是隐含的, z, 1) 隐含位是同质位并且总是向右推出。
    • @Tommy 在我看来,您发布的矩阵与我建议的矩阵不同,请注意我的第 3 列和第 3 行除了第 1 列之外都是空的. 以右下角元素为例,我说是H(2,2) 你说是1。
    • 非常感谢你们的回答。它有助于在该主题上拥有超过 1 个观点。真的很感激。事实证明,Hammer 的解决方案成功了。汤米,你的很接近,但我仍然注意到一些小的视觉差异。行与列的东西(并且需要转置)非常令人困惑。并感谢 Hammer 的详细描述。
    • @taber 感谢您告知我们!而且我同意当我不得不处理它时,移调让我发疯
    • 我认为它令人困惑的主要原因是,如果没有旋转或缩放,或者事情非常接近身份转换,那么你可以使用列或行专业,甚至不知道你是错了。
    【解决方案3】:

    Tommy 的回答对我有用,但我需要使用双精度,而不是浮点数。这也是代码的缩短版:

    CATransform3D MatToCATransform3D(cv::Mat H) {
        return {
            H.at<double>(0, 0), H.at<double>(1, 0), 0.0, H.at<double>(2, 0),
            H.at<double>(0, 1), H.at<double>(1, 1), 0.0, H.at<double>(2, 1),
            0.0, 0.0, 1.0, 0.0,
            H.at<double>(0, 2), H.at<double>(1, 2), 0.0f, H.at<double>(2, 2)
        };
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-08
      • 2013-10-27
      • 1970-01-01
      • 2011-07-31
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多