panolut_virtual_camera_common.cpp
Go to the documentation of this file.
00001 
00002 #include <ros/ros.h>
00003 #include <cv_bridge/cv_bridge.h>
00004 #include <image_transport/image_transport.h>
00005 #include <opencv2/core/core.hpp>
00006 #include <opencv2/imgproc/imgproc.hpp>
00007 
00008 #include "omnicamera/panolut_virtual_camera_common.h"
00009 
00010 using cv::Mat_;
00011 
00012 namespace omnicamera {
00013 
00014 void rotationMatrix(const double x, const double y, const double z, const double angle, Mat &R) {
00015 
00016   double norm = sqrt(x*x + y*y + z*z);
00017   double ux = x / norm;
00018   double uy = y / norm;
00019   double uz = z / norm;
00020   double c = cos(angle);
00021   double s = sin(angle);
00022 
00023   R = (Mat_<double>(3, 3) <<
00024          c+ux*ux*(1-c), ux*uy*(1-c)+uz*s, uz*ux*(1-c)-uy*s,
00025       ux*uy*(1-c)-uz*s,    c+uy*uy*(1-c), uz*uy*(1-c)+ux*s,
00026       ux*uz*(1-c)+uy*s, uy*uz*(1-c)-ux*s,    c+uz*uz*(1-c));
00027 }
00028 
00029 void panTiltToCart(const double pan, const double tilt, double &x, double &y, double &z) {
00030   x = cos(tilt) * cos(pan);
00031   y = cos(tilt) * sin(pan);
00032   z = sin(tilt);
00033 }
00034 
00035 void cartToPanTilt(const double x, const double y, const double z, double &pan, double &tilt) {
00036   tilt = atan2(z, hypot(x, y));
00037   pan = atan2(y, x);
00038 }
00039 
00040 void cameraMatrix(const double fovx, const double fovy, const double width, const double height, Mat &camMat) {
00041   double fx = 1 / tan(fovx / 2);
00042   double fy = 1 / tan(fovy / 2);
00043   double mx = width / 2;
00044   double my = height / 2;
00045   camMat = (Mat_<double> (3, 3) <<
00046       fx * mx,       0, mx,
00047             0, fy * my, my,
00048             0,       0,  1);
00049 }
00050 
00051 void cameraInverse(const double pan, const double tilt, const double fovx, const double fovy, const double width, const double height, Mat &camInv) {
00052   double x, y, z;
00053   panTiltToCart(pan, tilt, x, y, z);
00054 //  if (pan == 0.0 && tilt == 0.0) {
00055 //    printf("cameraInverse: pan %f, tilt %f corresponds to (%f, %f, %f)\n", pan, tilt, x, y, z);
00056 //  }
00057 
00058   Mat panR, tiltR, camR1, camR2;
00059   rotationMatrix(0, 0, 1, pan, panR);
00060   rotationMatrix(0, 1, 0, -tilt, tiltR);
00061   Mat camInWorld = (Mat_<double>(3, 3) << 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0);
00062   Mat camR = camInWorld * tiltR * panR;
00063 
00064   Mat K;
00065   cameraMatrix(fovx, fovy, width, height, K);
00066 
00067   camInv = (K * camR).inv(cv::DECOMP_SVD);
00068 }
00069 
00070 void updateVcamStitcher(const omnicamera::LookupStitcher &pano, const int panoWidth, const int panoHeight, const VirtualCameraConfig &vcamConfig, omnicamera::LookupStitcher &vcam) {
00071   // Handle viewport change, resize all virtual camera lookup tables.
00072   if (vcam.lutX[0].cols != vcamConfig.viewportWidth || vcam.lutY[0].rows != vcamConfig.viewportHeight) {
00073     for (int i = 0; i < pano.getLutCount(); i++) {
00074       vcam.lutX[i].create(vcamConfig.viewportHeight, vcamConfig.viewportWidth, CV_16UC1);
00075       vcam.lutY[i].create(vcamConfig.viewportHeight, vcamConfig.viewportWidth, CV_16UC1);
00076       vcam.lutA[i].create(vcamConfig.viewportHeight, vcamConfig.viewportWidth, CV_8UC1);
00077     }
00078   }
00079 
00080   Mat camInv;
00081   double panRad = vcamConfig.pan / 180.0 * M_PI;
00082   double tiltRad = vcamConfig.tilt / 180.0 * M_PI;
00083   double fovxRad = vcamConfig.horizontalFov / 180.0 * M_PI;
00084   double fovyRad = vcamConfig.verticalFov / 180.0 * M_PI;
00085   cameraInverse(panRad, tiltRad, fovxRad, fovyRad, vcamConfig.viewportWidth, vcamConfig.viewportHeight, camInv);
00086 
00087   Mat p = Mat_<double>(3, 1);
00088   Mat d = Mat_<double>(3, 1);
00089   for (int r = 0; r < vcamConfig.viewportHeight; r++) {
00090     for (int c = 0; c < vcamConfig.viewportWidth; c++) {
00091 
00092       // Create a point in image coordinates.
00093       p.at<double>(0, 0) = c;
00094       p.at<double>(1, 0) = r;
00095       p.at<double>(2, 0) = 1;
00096 
00097       // Get the world-coordinates direction for that image pixel.
00098       d = camInv * p;
00099       d = d / cv::norm(d);
00100 
00101       // Transform to pan and tilt, and then to panorama coordinates.
00102       double x, y, z, pan, tilt;
00103       x = d.at<double>(0, 0);
00104       y = d.at<double>(1, 0);
00105       z = d.at<double>(2, 0);
00106       cartToPanTilt(x, y, z, pan, tilt);
00107 //      if (r == vcamConfig.viewportHeight / 2 && c == vcamConfig.viewportWidth / 2) {
00108 //        printf("Image coordinates (%d, %d) corresponds to world point (%f, %f, %f), pan %f, tilt %f.\n", c, r, x, y, z, pan / M_PI * 180.0, tilt / M_PI * 180.0);
00109 //      }
00110       int panox = (int) round((0.5 + -pan / (2 * M_PI)) * (panoWidth - 1));
00111       int panoy = (int) round((0.5 + -tilt / M_PI) * (panoHeight - 1));
00112       panox = std::max(panox, 0);
00113       panox = std::min(panoWidth - 1, panox);
00114       panoy = std::max(panoy, 0);
00115       panoy = std::min(panoHeight - 1, panoy);
00116 
00117       for (int i = 0; i < pano.getLutCount(); i++) {
00118         vcam.lutX[i].at<ushort>(r, c) = pano.lutX[i].at<ushort>(panoy, panox);
00119         vcam.lutY[i].at<ushort>(r, c) = pano.lutY[i].at<ushort>(panoy, panox);
00120         vcam.lutA[i].at<uchar>(r, c) = pano.lutA[i].at<uchar>(panoy, panox);
00121       }
00122     }
00123   }
00124 }
00125 
00126 } // namespace omnicamera
 All Classes Namespaces Files Functions Variables Typedefs Defines


omnicamera
Author(s): Tomas Petricek / petrito1@cmp.felk.cvut.cz
autogenerated on Tue Dec 10 2013 14:26:53