Convert OpenCV findHomography perspective matrix in iOS 'CATransform3D

I would like to take the perspective transformation matrix returned from OpenCV findHomography

and convert it (either in C ++ or Objective-C) to iOS ' CATransform3D

. I would like them to be as close as possible to accurately reproducing the "warp" effect on the Core Graphics side. Sample code would really be appreciated!

From 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;
};

      

Similar questions:

Apply matrix using Core Graphics

converts opencv affine matrix to CGAffineTransform

+3


source to share


2 answers


Renouncement

I've never tried this, so take it with a grain of salt.

CATRansform3D is a 4x4 matrix that works with a 3-dimensional uniform vector (4x1) to produce another vector of the same type. I am assuming that when rendering, the objects described by the 4x1 vector have each element divided by the fourth element, and the third element is only used to determine which objects appear on top of them. Assuming this is correct ...

Reasoning

The 3x3 matrix returned by findHomography operates on a 2D homogeneous vector. This process can be represented in 4 stages

  • The first column of homography is multiplied by x
  • The second column of homography is multiplied by y
  • The third column of homography is multiplied by 1
  • the resulting 1st and 2nd vector elements are divided by the 3rd


You need this process to be replicated into a 4x4 vector in which I am taking the third element in the resulting vector does not make sense for your purposes.

Decision

Build your matrix like this (H is your homographic matrix)

[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)]

      

This clearly satisfies 1, 2 and 3. 4 is satisfied because the homogeneous element is always the last one. This is why a "homogeneous row" if you have to collide on the same line. The 1 on the 3rd line means that the z-component of the vector passes through the undeveloped one.

All of the above is done in lowercase notation (like openCV) to try not to confuse things. You can look at Tommy's answer to see what the column conversion looks like (you basically just wrap it). Note, however, that at this point Tommy and I disagree on how to build the matrix.

+4


source


From my reading of the documentation, m11

in CATransform3D

equivalent a

to CGAffineTransform

, m12

equivalent b

, etc.

As per your comment below, I understand that the OpenCV matrix returns at 3x3 (which in retrospect is the size you would expect). Thus, you must fill the other elements with the equivalent identity matrix. As per Hammer's answer, you want to keep the part that deals with the (usually implied) uniform coordinate in place, while at the same time filling everything else with personality.

[aside: my original answer was wrong. I edited it correctly since I posted the code and Hammer doesn't. This post is tagged as a community wiki to reflect that this is by no means my only answer]



So, I think you need:

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;
}

      

Or use cvGetReal1D

if you keep C ++ out of it.

+3


source







All Articles