00001
00002 #ifndef CAMERA_UNIVREPROJECTION_HPP
00003 #define CAMERA_UNIVREPROJECTION_HPP
00004
00005 #include <cmath>
00006 #include <iostream>
00007
00008 #include "kernel/jafarException.hpp"
00009 #include "kernel/jafarDebug.hpp"
00010
00011 #include "image/Image.hpp"
00012
00013 #include "camera/cameraPinhole.hpp"
00014 #include "camera/cameraBarreto.hpp"
00015
00016 #include "geom/t3dEuler.hpp"
00017
00018 namespace jafar {
00019 namespace camera {
00020
00032 template<typename _channeltype>
00033 void univReprojectionCylindric(CameraBarreto const& cameraBarreto,
00034 const jafar::image::Image& src_, jafar::image::Image& dst_, int interpolation_)
00035 {
00036 JFR_PRECOND(src_.width() == cameraBarreto.camera.width && src_.height() == cameraBarreto.camera.height,
00037 "reprojectionCylindric: source image size is invalid");
00038 JFR_PRECOND(src_.channels() == dst_.channels(),
00039 "reprojectionCylindric: images must have the same number of channel");
00040
00041 double phi, phiInt, phiExt, phiMin, phiMax, theta, thetaMin, thetaMax, phiStep, thetaStep;
00042 double r=0.0;
00043
00044 int nbPixel = 0,i,j;
00045 int dstNbCol = dst_.width(), dstNbRow = dst_.height();
00046 int ichannel, nbchannel = dst_.channels();
00047
00048
00049 jblas::vec3 direction, point3D;
00050 jblas::vec2 pixel, tmp;
00051
00052 _channeltype imaData;
00053
00054
00055
00056
00057 (cv::Mat)dst_ = cv::Mat::zeros(dst_.size(), dst_.type());
00058
00059
00060
00061
00062 pixel(1) = cameraBarreto.mirrorCenterV;
00063 pixel(0) = cameraBarreto.mirrorCenterU+cameraBarreto.maskRadius;
00064 cameraBarreto.imageToCameraFrameDirection<jblas::vec2,jblas::vec3>(pixel, direction);
00065 tmp(0) = direction(0); tmp(1) = direction(1);
00066 r = ublas::norm_2(tmp);
00067
00068 if (r<=1e-4)
00069 phiInt = (direction(2)>0.0)?0.5*M_PI:-0.5*M_PI;
00070 else
00071 phiInt = atan(direction(2)/r);
00072
00073
00074 pixel(1) = cameraBarreto.mirrorCenterV;
00075 pixel(0) = cameraBarreto.imageRadius + cameraBarreto.mirrorCenterU;
00076 cameraBarreto.imageToCameraFrameDirection<jblas::vec2,jblas::vec3>(pixel, direction);
00077 tmp(0) = direction(0); tmp(1) = direction(1);
00078 r = ublas::norm_2(tmp);
00079
00080 phiExt = atan(direction(2)/r);
00081
00082
00083
00084 thetaMax = M_PI/2.0;thetaMin = -3.0*M_PI/2.0;
00085 phiMin = (phiExt>phiInt)?phiInt:phiExt;
00086 phiMax = (phiExt>phiInt)?phiExt:phiInt;
00087
00088 thetaStep = (thetaMax-thetaMin)/dstNbCol;
00089 phiStep = (phiMax-phiMin)/dstNbRow;
00090
00091
00092
00093 for (j=0, phi = phiMax ; j<dstNbRow ; j++, phi -= phiStep)
00094 for (i=0, theta = thetaMin; i<dstNbCol ; i++, theta -= thetaStep, nbPixel++)
00095 {
00096 point3D(0) = cos(phi)*cos(theta);
00097 point3D(1) = cos(phi)*sin(theta);
00098 point3D(2) = sin(phi);
00099
00100 if ( cameraBarreto.project<jblas::vec3,jblas::vec2>(point3D,pixel) )
00101 for (ichannel = 0; ichannel < nbchannel; ichannel++)
00102 {
00103
00104 if (interpolation_)
00105 imaData = (_channeltype)src_.getSubPixelValue<_channeltype>(pixel(0),pixel(1),ichannel);
00106 else
00107 imaData = src_.getPixelValue<_channeltype>((int)pixel(0),(int)pixel(1),ichannel);
00108
00109
00110 dst_.setPixelValue<_channeltype>(imaData,i,j,ichannel);
00111 }
00112
00113 }
00114
00115 };
00116
00117
00125 bool pixelCyl2pixelPano (CameraBarreto const& cameraBarreto,
00126 const jafar::image::Image& cylIma,
00127 const jblas::vec2& pixelCyl,
00128 jblas::vec2& pixelPano)
00129 {
00130 JFR_PRECOND(pixelCyl(0)>=0 && pixelCyl(1)<cylIma.width() && pixelCyl(1)>=0 && pixelCyl(1)<cylIma.height(),
00131 "pixelCyl2pixelPano : specified pixel is out of cylindrical image");
00132
00133 double phi, phiInt, phiExt, phiMin, phiMax, theta, thetaMin, thetaMax, phiStep, thetaStep;
00134 double r=0.0;
00135 int dstNbCol = cylIma.width(), dstNbRow = cylIma.height();
00136
00137 jblas::vec2 pixel;
00138 jblas::vec3 direction, point3D;
00139
00140
00141
00142
00143 pixel(1) = cameraBarreto.mirrorCenterV;
00144 pixel(0) = cameraBarreto.mirrorCenterU+cameraBarreto.maskRadius;
00145 cameraBarreto.imageToCameraFrameDirection<jblas::vec2,jblas::vec3>(pixel, direction);
00146 pixel(0) = direction(0); pixel(1) = direction(1);
00147 r = ublas::norm_2(pixel);
00148
00149 if (r<=1e-4)
00150 phiInt = (direction(2)>0.0)?0.5*M_PI:-0.5*M_PI;
00151 else
00152 phiInt = atan(direction(2)/r);
00153
00154
00155 pixel(1) = cameraBarreto.mirrorCenterV;
00156 pixel(0) = cameraBarreto.imageRadius + cameraBarreto.mirrorCenterU;
00157 cameraBarreto.imageToCameraFrameDirection<jblas::vec2,jblas::vec3>(pixel, direction);
00158 pixel(0) = direction(0); pixel(1) = direction(1);
00159 r = ublas::norm_2(pixel);
00160
00161 phiExt = atan(direction(2)/r);
00162
00163
00164
00165 thetaMax = M_PI/2.0;thetaMin = -3.0*M_PI/2.0;
00166 phiMin = (phiExt>phiInt)?phiInt:phiExt;
00167 phiMax = (phiExt>phiInt)?phiExt:phiInt;
00168
00169 thetaStep = (thetaMax-thetaMin)/dstNbCol;
00170 phiStep = (phiMax-phiMin)/dstNbRow;
00171
00172
00173
00174
00175 theta = thetaMin - pixelCyl(0)*thetaStep;
00176 phi = phiMax - pixelCyl(1)*phiStep;
00177
00178 point3D(0) = cos(phi)*cos(theta);
00179 point3D(1) = cos(phi)*sin(theta);
00180 point3D(2) = sin(phi);
00181
00182 return cameraBarreto.project<jblas::vec3,jblas::vec2>(point3D,pixelPano);
00183
00184 };
00185
00201 template<typename _channeltype>
00202 void univReprojectionPerspective(CameraParabolicBarreto const& cameraBarreto,
00203 const jafar::image::Image& src_,
00204 jafar::image::Image& dst_,
00205 double elev_, double azim_, double roll_, double vOpen_, int interpolation_)
00206 {
00207 JFR_PRECOND(src_.width() == cameraBarreto.camera.width && src_.height() == cameraBarreto.camera.height,
00208 "reprojectionPerspective: confllict between source image size and calibration parameters.");
00209 JFR_PRECOND(src_.channels() == dst_.channels(),
00210 "reprojectionPerspective: images must have the same number of channel.");
00211
00212 double u0out, v0out, fu, fv, hOpen;
00213 int i=3, j, ichannel, nbchannel = dst_.channels();
00214 int dstNbCol = dst_.width(), dstNbRow = dst_.height();
00215
00216 jblas::vec4 pth, ptest;
00217 jblas::vec3 direction, point3D, pt;
00218 jblas::vec2 pixel, pixelp, tmp;
00219 jblas::mat44 matM;
00220 jblas::mat33 matR, tmatR, matR1, matR2;
00221
00222 _channeltype imaData;
00223
00224 jafar::geom::T3DEuler maT3DEuler;
00225 jafar::camera::CameraPinhole vCam;
00226
00227
00228
00229 hOpen = dstNbCol*vOpen_/dstNbRow;
00230 u0out = (double)(dstNbCol-1)/2.0;
00231 v0out = (double)(dstNbRow-1)/2.0;
00232 fv = dstNbRow/(2.0*tan(vOpen_/2.0));
00233 fu = dstNbCol/(2.0*tan(hOpen/2.0));
00234 vCam.setParameters(dstNbCol, dstNbRow, u0out, v0out, fu, fv);
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 maT3DEuler.setValue(0,0,0,roll_,0,0);
00257 matM = maT3DEuler.getM();
00258 for (i=0;i<3;i++)
00259 for (j=0;j<3;j++)
00260 matR2(i,j) = matM(i,j);
00261
00262 maT3DEuler.setValue(0,0,0,M_PI+azim_,0,-elev_ - M_PI/2.0);
00263 matM = maT3DEuler.getM();
00264 for (i=0;i<3;i++)
00265 for (j=0;j<3;j++)
00266 matR1(i,j) = matM(i,j);
00267
00268 matR = ublas::prod(matR1,matR2);
00269
00270
00271
00272
00273 (cv::Mat)dst_ = cv::Mat::zeros(dst_.size(), dst_.type());
00274
00275
00276 for (j=0;j<dstNbRow;j++)
00277 {
00278 pixelp(1) = j;
00279 for (i=0;i<dstNbCol;i++)
00280 {
00281 pixelp(0) = i;
00282 vCam.imageToCameraFrame<jblas::vec2,jblas::vec3>(pixelp,pt);
00283
00284 point3D = ublas::prod(matR,pt);
00285
00286 if (cameraBarreto.project<jblas::vec3,jblas::vec2>(point3D,pixel) )
00287 for (ichannel = 0; ichannel < nbchannel; ichannel++)
00288 {
00289
00290
00291 if (interpolation_)
00292 imaData = (_channeltype)src_.getSubPixelValue<_channeltype>(pixel(0),pixel(1),ichannel);
00293 else
00294 imaData = src_.getPixelValue<_channeltype>((int)pixel(0),(int)pixel(1),ichannel);
00295
00296
00297 dst_.setPixelValue<_channeltype>(imaData,i,j,ichannel);
00298
00299 }
00300
00301
00302 }
00303
00304 }
00305
00306
00307 };
00308
00309 }
00310
00311 }
00312
00313 #endif // CAMERA_GENREPROJ_HPP
00314