Advertisement
jack06215

[OpenCV] perspective slider

Jul 8th, 2020
451
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.17 KB | None | 0 0
  1. #include <opencv2/core/core.hpp>
  2. #include <opencv2/imgproc/imgproc.hpp>
  3. #include <opencv2/highgui/highgui.hpp>
  4. #define _USE_MATH_DEFINES
  5. #include <math.h>
  6. #include <iostream>
  7.  
  8.  
  9. using namespace cv;
  10. using namespace std;
  11.  
  12. static double rad2Deg(double rad) { return rad * (180 / M_PI); }//Convert radians to degrees
  13. static double deg2Rad(double deg) { return deg * (M_PI / 180); }//Convert degrees to radians
  14.  
  15. double    theta;
  16. double    phi;
  17. double    gamma;
  18. double    scale;
  19. double    fovy;
  20.  
  21. int    g_theta_slider;
  22. int    g_phi_slider;
  23. int    g_gamma_slider;
  24. int theta_slider[720];
  25. int phi_slider[720];
  26. int gamma_slider[720];
  27. int fovy_slider[400];
  28.  
  29.  
  30. int    g_scale_slider = 1;
  31. int    g_fovy_slider = 1;
  32.  
  33. const int    g_max_slider = 360;
  34.  
  35. Mat m, disp, warp;
  36. vector<Point2f> corners;
  37.  
  38.  
  39. void warpMatrix(Size sz, Mat& M, vector<Point2f>* corners) {
  40.     double theta = (int)theta_slider[g_theta_slider];
  41.     double phi = (int)phi_slider[g_phi_slider];
  42.     double gamma = (int)gamma_slider[g_gamma_slider];
  43.     double scale = g_scale_slider;
  44.     double fovy = (int)fovy_slider[g_fovy_slider];
  45.  
  46.     double st = sin(deg2Rad(theta));
  47.     double ct = cos(deg2Rad(theta));
  48.     double sp = sin(deg2Rad(phi));
  49.     double cp = cos(deg2Rad(phi));
  50.     double sg = sin(deg2Rad(gamma));
  51.     double cg = cos(deg2Rad(gamma));
  52.  
  53.     st = sin(theta);
  54.     ct = cos(theta);
  55.     sp = sin(phi);
  56.     cp = cos(phi);
  57.     sg = sin(gamma);
  58.     cg = cos(gamma);
  59.  
  60.     double halfFovy = fovy * 0.5;
  61.     double d = hypot(sz.width, sz.height);
  62.     double sideLength = scale * d / cos(deg2Rad(halfFovy));
  63.     double h = d / (2.0 * sin(deg2Rad(halfFovy)));
  64.     double n = h - (d / 2.0);
  65.     double f = h + (d / 2.0);
  66.  
  67.     Mat F = Mat(4, 4, CV_64FC1);            //Allocate 4x4 transformation matrix F
  68.     Mat Rtheta = Mat::eye(4, 4, CV_64FC1);  //Allocate 4x4 rotation matrix around Z-axis by theta degrees
  69.     Mat Rphi = Mat::eye(4, 4, CV_64FC1);    //Allocate 4x4 rotation matrix around X-axis by phi degrees
  70.     Mat Rgamma = Mat::eye(4, 4, CV_64FC1);  //Allocate 4x4 rotation matrix around Y-axis by gamma degrees
  71.  
  72.     Mat T = Mat::eye(4, 4, CV_64FC1);       //Allocate 4x4 translation matrix along Z-axis by -h units
  73.     Mat P = Mat::zeros(4, 4, CV_64FC1);     //Allocate 4x4 projection matrix
  74.  
  75.     Mat A1 = (Mat_<double>(4, 3) <<
  76.         1, 0, -sz.width / 2,
  77.         0, 1, -sz.height / 2,
  78.         0, 0, 0,
  79.         0, 0, 1);
  80.  
  81.     //Rtheta
  82.     Rtheta.at<double>(0, 0) = Rtheta.at<double>(1, 1) = ct;
  83.     Rtheta.at<double>(0, 1) = -st; Rtheta.at<double>(1, 0) = st;
  84.     //Rphi
  85.     Rphi.at<double>(1, 1) = Rphi.at<double>(2, 2) = cp;
  86.     Rphi.at<double>(1, 2) = -sp; Rphi.at<double>(2, 1) = sp;
  87.     //Rgamma
  88.     Rgamma.at<double>(0, 0) = Rgamma.at<double>(2, 2) = cg;
  89.     Rgamma.at<double>(0, 2) = sg; Rgamma.at<double>(2, 0) = sg;
  90.  
  91.     Mat R = Rphi * Rtheta * Rgamma;
  92.  
  93.     //T
  94.     T.at<double>(2, 3) = -h;
  95.    
  96.     //P
  97.     P.at<double>(0, 0) = P.at<double>(1, 1) = 1.0 / tan(deg2Rad(halfFovy));
  98.     P.at<double>(2, 2) = -(f + n) / (f - n);
  99.     P.at<double>(2, 3) = -(2.0 * f * n) / (f - n);
  100.     P.at<double>(3, 2) = -1.0;
  101.  
  102.     Mat A2 = (Mat_<double>(3, 4) <<
  103.         f, 0, sz.width / 2, 0,
  104.         0, f, sz.height / 2, 0,
  105.         0, 0, 1, 0);
  106.     Mat A3 = A1 * A2;
  107.  
  108.     //Compose transformations
  109.     F = P * (T * R);    //Matrix-multiply to produce master matrix
  110.                         //F = A2*(T*(R*A1));//Matrix-multiply to produce master matrix
  111.  
  112.                         //Transform 4x4 points
  113.     double ptsIn[4 * 3];
  114.     double ptsOut[4 * 3];
  115.     double halfW = sz.width / 2, halfH = sz.height / 2;
  116.  
  117.     ptsIn[0] = -halfW; ptsIn[1] = halfH;
  118.     ptsIn[3] = halfW; ptsIn[4] = halfH;
  119.     ptsIn[6] = halfW; ptsIn[7] = -halfH;
  120.     ptsIn[9] = -halfW; ptsIn[10] = -halfH;
  121.  
  122.     ptsIn[2] = ptsIn[5] = ptsIn[8] = ptsIn[11] = 0;//Set Z component to zero for all 4 components
  123.  
  124.     Mat ptsInMat(1, 4, CV_64FC3, ptsIn);
  125.     Mat ptsOutMat(1, 4, CV_64FC3, ptsOut);
  126.  
  127.     perspectiveTransform(ptsInMat, ptsOutMat, F);//Transform points
  128.  
  129.                                                  //Get 3x3 transform and warp image
  130.     Point2f ptsInPt2f[4];
  131.     Point2f ptsOutPt2f[4];
  132.  
  133.     for (int i = 0; i < 4; i++) {
  134.         Point2f ptIn(ptsIn[i * 3 + 0], ptsIn[i * 3 + 1]);
  135.         Point2f ptOut(ptsOut[i * 3 + 0], ptsOut[i * 3 + 1]);
  136.         ptsInPt2f[i] = ptIn + Point2f(halfW, halfH);
  137.         ptsOutPt2f[i] = (ptOut + Point2f(1, 1)) * (sideLength * 0.5);
  138.     }
  139.  
  140.     M = getPerspectiveTransform(ptsInPt2f, ptsOutPt2f);
  141.  
  142.     //Load corners vector
  143.     if (corners) {
  144.         corners->clear();
  145.         corners->push_back(ptsOutPt2f[0]);  //Push Top Left corner
  146.         corners->push_back(ptsOutPt2f[1]);  //Push Top Right corner
  147.         corners->push_back(ptsOutPt2f[2]);  //Push Bottom Right corner
  148.         corners->push_back(ptsOutPt2f[3]);  //Push Bottom Left corner
  149.     }
  150. }
  151.  
  152. void warpImage(const Mat& src, Mat& dst,Mat& M, vector<Point2f>& corners) {
  153.  
  154.     double theta = (int)g_theta_slider;
  155.     double phi = (int)g_phi_slider;
  156.     double gamma = (int)g_gamma_slider;
  157.     double scale = g_scale_slider;
  158.     double fovy = g_fovy_slider;
  159.  
  160.     double halfFovy = fovy * 0.5;
  161.     double d = hypot(src.cols, src.rows);
  162.     double sideLength = scale * d / cos(deg2Rad(halfFovy));
  163.  
  164.     warpMatrix(src.size(), M, &corners);                        //Compute warp matrix
  165.     warpPerspective(src, dst, M, Size(sideLength, sideLength)); //Do actual image warp
  166.     circle(dst, Point(corners.at(0)), 3, CV_RGB(255, 0, 0), 3);
  167.     circle(dst, Point(corners.at(1)), 3, CV_RGB(0, 255, 0), 3);
  168.     circle(dst, Point(corners.at(2)), 3, CV_RGB(0, 0, 255), 3);
  169.     circle(dst, Point(corners.at(3)), 3, CV_RGB(255, 255, 0), 3);
  170.  
  171.     cout << dst.size() << endl;
  172. }
  173.  
  174. void on_trackbar(int, void*)
  175. {
  176.     warpImage(m, disp, warp, corners);
  177. }
  178.  
  179.  
  180. int main(void) {
  181.  
  182.     VideoCapture cap(0);
  183.     waitKey(1000);
  184.     namedWindow("Disp");
  185.     //m = imread("WIN_20160527_16_21_39_Pro.jpg");
  186.     for (int i = 0; i < sizeof(fovy_slider) / sizeof(fovy_slider[0]); i++)
  187.     {
  188.         fovy_slider[i] = i - 100;
  189.     }
  190.     for (int i = 0; i < sizeof(gamma_slider) / sizeof(gamma_slider[0]); i++)
  191.     {
  192.         theta_slider[i] = i - 360;
  193.         phi_slider[i] = i - 360;
  194.         gamma_slider[i] = i - 360;
  195.         //cout << i - 360 << endl;
  196.     }
  197.     createTrackbar("z-axix", "Disp", &g_theta_slider, 719, &on_trackbar);
  198.     createTrackbar("y-axix", "Disp", &g_phi_slider, 719, &on_trackbar);
  199.     createTrackbar("x-axix", "Disp", &g_gamma_slider, 719, &on_trackbar);
  200.     createTrackbar("fovy", "Disp", &g_fovy_slider, 200, &on_trackbar);
  201.     while (cap.isOpened()) {
  202.         cap >> m;
  203.         warpImage(m, disp, warp, corners);
  204.         imshow("Disp2", disp);
  205.         waitKey(33);
  206.     }
  207.     return 0;
  208. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement