Ask Your Question
1

Interpolation of transformation matrix

asked 2019-09-20 10:14:45 -0600

karlosos gravatar image

Is it possible to interpolate transformation matrix? I want to have rough homography for every frame between two frames for which homography was calculated manualy.

For example there's frame 0 with calculated transformation matrix H and frame 101 with calculated matrix H'. Granted that camera movement is even I want to find 100 transformation matrices to every frame between 0 and 101.

image description

Or is there any simplier solution for this problem?

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
3

answered 2019-09-20 17:01:30 -0600

Eduardo gravatar image

One solution is to interpolate directly the elements of the homography matrix, see @LBerger answer.

Here a video result.


Another possibility consists in exploiting the underlying geometrical meaning of the homography transformation, that is the transformation induced by a camera displacement for a planar scene and a generic motion. See this tutorial for some information.

Here a video result.


Most likely it is the first solution that you want and that is also the simplest.

Nevertheless, it is important to recall what the homography transformation means physically.

The code to produce the results:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

namespace
{
  enum Pattern { CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID };

  void calcChessboardCorners(Size boardSize, float squareSize, vector<Point3f>& corners, Pattern patternType = CHESSBOARD)
  {
    corners.resize(0);

    switch (patternType) {
    case CHESSBOARD:
    case CIRCLES_GRID:
      for (int i = 0; i < boardSize.height; i++)
        for (int j = 0; j < boardSize.width; j++)
          corners.push_back(Point3f(float(j*squareSize),
            float(i*squareSize), 0));
      break;

    case ASYMMETRIC_CIRCLES_GRID:
      for (int i = 0; i < boardSize.height; i++)
        for (int j = 0; j < boardSize.width; j++)
          corners.push_back(Point3f(float((2 * j + i % 2)*squareSize),
            float(i*squareSize), 0));
      break;

    default:
      CV_Error(Error::StsBadArg, "Unknown pattern type\n");
    }
  }

  Matx33d computeHomography(const Matx33d& R_1to2, const Matx31d& tvec_1to2, double d_inv, const Matx31d& normal)
  {
    Matx33d homography = R_1to2 + d_inv * tvec_1to2*normal.t();
    return homography;
  }
}

int main()
{
  Mat img1 = imread("left01.jpg");
  Mat img2 = imread("left02.jpg");
  Mat img3 = imread("left03.jpg");

  Size patternSize(9, 6);
  vector<Point2f> corners1, corners2, corners3;
  bool found1 = findChessboardCorners(img1, patternSize, corners1);
  bool found2 = findChessboardCorners(img2, patternSize, corners2);
  bool found3 = findChessboardCorners(img3, patternSize, corners3);

  if (!found1 || !found2 || !found3) {
    cout << "Error, cannot find the chessboard corners in images." << endl;
    return 0;
  }

  Matx33d H_1_to_2 = findHomography(corners1, corners2);
  cout << "H_1_to_2:\n" << H_1_to_2 << endl;

  Matx33d H_1_to_3 = findHomography(corners1, corners3);
  cout << "H_1_to_3:\n" << H_1_to_3 << endl;

  int ninterp = 10;
  // interpolation 1
  std::cout << "\nINTERPOLATION 1" << std::endl;
  for (int idx = 1; idx <= ninterp; idx++) {
    Matx33d H_2_to_3_interp = Matx33d::eye();
    for (int i = 0; i < 3; i++) {
      for (int j = 0; j < 3; j++) {
        H_2_to_3_interp(i, j) = (H_1_to_3(i, j) - H_1_to_2(i, j)) * (idx / static_cast<double>(ninterp));
      }
    }

    Matx33d H_1_to_3_interp = H_1_to_2 + H_2_to_3_interp;
    cout << "H_1_to_3_interp:\n" << H_1_to_3_interp << endl;

    Mat img3_warp;
    warpPerspective(img1, img3_warp, H_1_to_3_interp, img1.size());

    Mat img_draw_warp3;
    hconcat(img2, img3_warp, img_draw_warp3);
    hconcat(img_draw_warp3, img3, img_draw_warp3);

    imshow("H_1_to_3_interp", img_draw_warp3);
    waitKey();
  }

  // interpolation 2
  Matx33d H_2_to_3 = H_1_to_3 * H_1_to_2.inv();
  double h33_inv = 1 / H_2_to_3(2, 2);
  H_2_to_3 = H_2_to_3 * h33_inv;

  std::cout << "\nINTERPOLATION 2" << std::endl;
  vector<Mat> Rs_decomp, ts_decomp, normals_decomp;
  Matx33d cameraMatrix = Matx33d::eye();
  int solutions = decomposeHomographyMat(H_2_to_3, cameraMatrix, Rs_decomp, ts_decomp, normals_decomp);
  std::cout << "solutions: " << solutions << std::endl;
  if (solutions == 0) {
    return 0;
  }

  for (int solution = 0; solution < solutions; solution++) {
    std::cout << "\nsolution number: " << solution << std::endl;
    Matx31d rvec, tvec, normal;
    tvec = ts_decomp[solution];
    normal = normals_decomp[solution];
    Matx33d R = Rs_decomp[solution];

    std::cout << "\nH_2_to_3:\n" << H_2_to_3 << std::endl;
    Matx33d H_2_to_3_reconstruct = computeHomography(R, tvec, 1, normal);
    double ...
(more)
edit flag offensive delete link more
0

answered 2019-09-20 10:55:59 -0600

LBerger gravatar image

Idea :

linear transformation Hij +d(H'ij-Hij)/100

or H' = H X Y=X^(1/100) then Hn= H Y^n

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2019-09-20 10:14:45 -0600

Seen: 1,230 times

Last updated: Sep 20 '19