00001
00002
00003 #ifndef CAMERA_REPROJECTION_HPP
00004 #define CAMERA_REPROJECTION_HPP
00005
00006 #include <cmath>
00007 #include <iostream>
00008
00009 #include "kernel/jafarException.hpp"
00010 #include "kernel/jafarDebug.hpp"
00011
00012 #include "image/Image.hpp"
00013
00014 #include "camera/cameraBarreto.hpp"
00015
00016 namespace jafar {
00017 namespace camera {
00018
00024 template<typename _channeltype>
00025 void reprojectionCylindric(CameraParabolicBarreto const& cameraBarreto,
00026 const jafar::image::Image& src_, jafar::image::Image& dst_, int interpolation_)
00027 {
00028 JFR_PRECOND(src_.width() == cameraBarreto.camera.width && src_.height() == cameraBarreto.camera.height,
00029 "reprojectionCylindric: source image size is invalid");
00030 JFR_PRECOND(src_.channels()==1 && dst_.channels()==1,
00031 "reprojectionCylindric: images must be mono channel");
00032
00033
00034 double h = 2*cameraBarreto.p * cameraBarreto.imageRadius / (cameraBarreto.mirrorDiameter/2);
00035
00036
00037 double radiusmin = cameraBarreto.maskRadius;
00038 double radiusmax = cameraBarreto.imageRadius;
00039
00040 int dstNbCol = dst_.width(), dstNbRow = dst_.height();
00041 int nbPixel = 0, i, j;
00042
00043 double theta = 0.0, thetaMin = 0.0, thetaMax = 2*M_PI, thetaStep;
00044 double phi = 0.0, phiMin, phiMax, phiStep;
00045 double x, y, radius = 0.0;
00046
00047 _channeltype imaData;
00048
00049
00050 phiMin = atan2 (radiusmin*radiusmin-h*h,2*radiusmin*h);
00051 phiMax = atan2 (radiusmax*radiusmax-h*h,2*radiusmax*h);
00052
00053
00054 thetaStep = (thetaMax-thetaMin)/dstNbCol;
00055 phiStep = (phiMax-phiMin)/dstNbRow;
00056
00057
00058 for (j=0, phi = phiMax ; j<dstNbRow ; j++, phi -= phiStep)
00059 {
00060 radius = h*(1+sin(phi))/cos(phi);
00061
00062 for (i=0, theta = thetaMin; i<dstNbCol ; i++, theta += thetaStep, nbPixel++)
00063 {
00064 x = radius*cos(theta) + cameraBarreto.camera.u0;
00065 y = radius*sin(theta) + cameraBarreto.camera.v0;
00066
00067
00068 if (interpolation_)
00069 imaData = (_channeltype)src_.getSubPixelValue<_channeltype>(x,y);
00070 else
00071 imaData = src_.getPixelValue<_channeltype>((int)x,(int)y);
00072
00073
00074 dst_.setPixelValue<_channeltype>(imaData,i,j);
00075
00076 }
00077 }
00078
00079 };
00080
00081
00082
00090 template<typename _channeltype>
00091 void reprojectionPlane(CameraParabolicBarreto const& cameraBarreto,
00092 const jafar::image::Image& src_,
00093 jafar::image::Image& dst_,
00094 double planedist_, double areawidth_, int interpolation_)
00095 {
00096 JFR_PRECOND(src_.width() == cameraBarreto.camera.width && src_.height() == cameraBarreto.camera.height,
00097 "reprojectionPlane: source image size is invalid");
00098 JFR_PRECOND(src_.channels()==1 && dst_.channels()==1,
00099 "reprojectionCylindric: images must be mono channel");
00100
00101
00102 double h = 2*cameraBarreto.p * cameraBarreto.imageRadius / (cameraBarreto.mirrorDiameter/2);
00103
00104 int dstNbCol = dst_.width(), dstNbRow = dst_.height();
00105 int i, j;
00106
00107 double x, xMin, xMax, xStep;
00108 double y, yMin, yMax, yStep;
00109 double xMirror, xImage, yImage, yMirror;
00110 double phi, theta;
00111 double radiusOnPlane, radiusOnMirror;
00112
00113 _channeltype imaData;
00114
00115
00116 xMin = yMin = -areawidth_;
00117 xMax = yMax = areawidth_;
00118
00119
00120 xStep = 2*areawidth_/dstNbCol;
00121 yStep = 2*areawidth_/dstNbRow;
00122
00123
00124 for (j=0, y = yMin; y<yMax; y+=yStep, j++)
00125 for (i=0, x = xMin; x<xMax; x+=xStep, i++)
00126 {
00127 radiusOnPlane = sqrt(x*x+y*y);
00128
00129
00130 phi = -atan2(planedist_,radiusOnPlane);
00131 theta = atan2(y,x);
00132
00133
00134 radiusOnMirror = h*(1+sin(phi))/cos(phi);
00135 xMirror = radiusOnMirror*cos(theta);
00136 yMirror = radiusOnMirror*sin(theta);
00137
00138
00139 xImage = cameraBarreto.camera.u0 + xMirror;
00140 yImage = cameraBarreto.camera.v0 + yMirror;
00141
00142
00143 if (interpolation_)
00144 imaData = (_channeltype)src_.getSubPixelValue<_channeltype>(xImage,yImage);
00145 else
00146 imaData = src_.getPixelValue<_channeltype>((int)xImage,(int)yImage);
00147
00148 dst_.setPixelValue<_channeltype>(imaData,i,j);
00149
00150 }
00151
00152 };
00153
00163 template<typename _channeltype>
00164 void reprojectionPerspective(CameraParabolicBarreto const& cameraBarreto,
00165 const jafar::image::Image& src_,
00166 jafar::image::Image& dst_,
00167 double elev_, double azim_, double vOpen_, int interpolation_)
00168 {
00169 JFR_PRECOND(src_.width() == cameraBarreto.camera.width && src_.height() == cameraBarreto.camera.height,
00170 "reprojectionPerspective: source image size is invalid");
00171 JFR_PRECOND(src_.channels()==1 && dst_.channels()==1,
00172 "reprojectionCylindric: images must be mono channel");
00173
00174
00175 double h = 2*cameraBarreto.p * cameraBarreto.imageRadius / (cameraBarreto.mirrorDiameter/2);
00176
00177 int dstNbCol = dst_.width(), dstNbRow = dst_.height();
00178 int i,j;
00179
00180 double focal, u0, v0;
00181 double ur,vr;
00182 double phi, dPhi, theta, dTheta;
00183 double xImage, yImage, radius;
00184
00185 _channeltype imaData;
00186
00187
00188 u0 = (double)(dstNbCol-1)/2;
00189 v0 = (double)(dstNbRow-1)/2;
00190 focal = dstNbRow/(2*tan(vOpen_/2));
00191
00192
00193 for (j=0;j<dstNbRow;j++)
00194 {
00195 vr = -(double)j+v0;
00196 dPhi = atan2(vr,focal);
00197 phi = elev_+dPhi;
00198 radius = h*(1+sin(phi))/cos(phi);
00199
00200 for (i=0;i<dstNbCol;i++)
00201 {
00202 ur = (double)i-u0;
00203 dTheta = atan2(ur,focal);
00204 theta = dTheta + azim_;
00205
00206
00207 xImage = cameraBarreto.camera.u0 + radius*cos(theta);
00208 yImage = cameraBarreto.camera.v0 + radius*sin(theta);
00209
00210
00211 if (interpolation_)
00212 imaData = (_channeltype)src_.getSubPixelValue<_channeltype>(xImage,yImage);
00213 else
00214 imaData = src_.getPixelValue<_channeltype>((int)xImage,(int)yImage);
00215
00216 dst_.setPixelValue<_channeltype>(imaData,i,j);
00217
00218 }
00219 }
00220 };
00221
00222 }
00223 }
00224
00225 #endif // CAMERA_REPROJECTION_HPP
00226