00001
00002
00027 #include <hugin_config.h>
00028
00029 #include <stdlib.h>
00030
00031 #include "PanoToolsInterface.h"
00032
00033 #include <vector>
00034 #include <set>
00035 #include <hugin_utils/utils.h>
00036 #include <hugin_utils/stl_utils.h>
00037 #include <panodata/PanoramaData.h>
00038 #include <panodata/StandardImageVariableGroups.h>
00039
00040 namespace HuginBase { namespace PTools {
00041
00042 Transform::~Transform()
00043 {
00044 if (!m_initialized) {
00045 freeImage(m_srcImage);
00046 freeImage(m_dstImage);
00047 }
00048 }
00049
00050 void Transform::updatePTData(const vigra::Diff2D &srcSize,
00051 const VariableMap & srcVars,
00052 Lens::LensProjectionFormat & srcProj,
00053 const vigra::Diff2D & destSize,
00054 PanoramaOptions::ProjectionFormat & destProj,
00055 const std::vector<double> & destProjParam,
00056 double destHFOV)
00057 {
00058 if (m_initialized) {
00059 freeImage(m_srcImage);
00060 freeImage(m_dstImage);
00061 }
00062
00063
00064 setFullImage(m_srcImage, srcSize, 0,
00065 srcVars, srcProj, true);
00066 setDestImage(m_dstImage, destSize, 0, destProj, destProjParam, destHFOV);
00067 }
00068
00069
00070 void Transform::createTransform(const PanoramaData & pano, unsigned int imgNr,
00071 const PanoramaOptions & dest, vigra::Diff2D srcSize)
00072 {
00073 const SrcPanoImage & img = pano.getImage(imgNr);
00074 if (srcSize.x == 0 && srcSize.y == 0) {
00075 srcSize.x = img.getWidth();
00076 srcSize.y = img.getHeight();
00077 }
00078 createTransform(srcSize,
00079 pano.getImageVariables(imgNr),
00080 (Lens::LensProjectionFormat)pano.getImage(imgNr).getProjection(),
00081 vigra::Diff2D(dest.getWidth(), dest.getHeight()),
00082 dest.getProjection(),
00083 dest.getProjectionParameters(),
00084 dest.getHFOV(),
00085 vigra::Diff2D(img.getWidth(), img.getHeight()));
00086 }
00087
00088 void Transform::createInvTransform(const SrcPanoImage & src, const PanoramaOptions & dest)
00089 {
00090 VariableMap vars;
00091
00092 vars.insert(make_pair(std::string("v"), Variable(std::string("v"), src.getHFOV())));
00093 vars.insert(make_pair(std::string("a"), Variable("a", src.getRadialDistortion()[0])));
00094 vars.insert(make_pair(std::string("b"), Variable("b", src.getRadialDistortion()[1])));
00095 vars.insert(make_pair(std::string("c"), Variable("c", src.getRadialDistortion()[2])));
00096 vars.insert(make_pair(std::string("d"), Variable("d", src.getRadialDistortionCenterShift().x)));
00097 vars.insert(make_pair(std::string("e"), Variable("e", src.getRadialDistortionCenterShift().y)));
00098 vars.insert(make_pair(std::string("g"), Variable("g", src.getShear().x)));
00099 vars.insert(make_pair(std::string("t"), Variable("t", src.getShear().y)));
00100
00101 vars.insert(make_pair(std::string("r"), Variable("r", src.getRoll())));
00102 vars.insert(make_pair(std::string("p"), Variable("p", src.getPitch())));
00103 vars.insert(make_pair(std::string("y"), Variable("y", src.getYaw())));
00104
00105 vars.insert(make_pair(std::string("TrX"), Variable("TrX", src.getX())));
00106 vars.insert(make_pair(std::string("TrY"), Variable("TrY", src.getY())));
00107 vars.insert(make_pair(std::string("TrZ"), Variable("TrZ", src.getZ())));
00108
00109 vars.insert(make_pair(std::string("Tpy"), Variable("Tpy", src.getTranslationPlaneYaw())));
00110 vars.insert(make_pair(std::string("Tpp"), Variable("Tpp", src.getTranslationPlanePitch())));
00111
00112 createInvTransform(src.getSize(),
00113 vars,
00114 (Lens::LensProjectionFormat) src.getProjection(),
00115 dest.getSize(),
00116 dest.getProjection(),
00117 dest.getProjectionParameters(),
00118 dest.getHFOV(),
00119 src.getSize());
00120 }
00121
00122 void Transform::createTransform(const SrcPanoImage & src, const PanoramaOptions & dest)
00123 {
00124
00125 VariableMap vars;
00126
00127 vars.insert(make_pair(std::string("v"), Variable(std::string("v"), src.getHFOV())));
00128 vars.insert(make_pair(std::string("a"), Variable("a", src.getRadialDistortion()[0])));
00129 vars.insert(make_pair(std::string("b"), Variable("b", src.getRadialDistortion()[1])));
00130 vars.insert(make_pair(std::string("c"), Variable("c", src.getRadialDistortion()[2])));
00131 vars.insert(make_pair(std::string("d"), Variable("d", src.getRadialDistortionCenterShift().x)));
00132 vars.insert(make_pair(std::string("e"), Variable("e", src.getRadialDistortionCenterShift().y)));
00133 vars.insert(make_pair(std::string("g"), Variable("g", src.getShear().x)));
00134 vars.insert(make_pair(std::string("t"), Variable("t", src.getShear().y)));
00135
00136 vars.insert(make_pair(std::string("r"), Variable("r", src.getRoll())));
00137 vars.insert(make_pair(std::string("p"), Variable("p", src.getPitch())));
00138 vars.insert(make_pair(std::string("y"), Variable("y", src.getYaw())));
00139
00140 vars.insert(make_pair(std::string("TrX"), Variable("TrX", src.getX())));
00141 vars.insert(make_pair(std::string("TrY"), Variable("TrY", src.getY())));
00142 vars.insert(make_pair(std::string("TrZ"), Variable("TrZ", src.getZ())));
00143
00144 vars.insert(make_pair(std::string("Tpy"), Variable("Tpy", src.getTranslationPlaneYaw())));
00145 vars.insert(make_pair(std::string("Tpp"), Variable("Tpp", src.getTranslationPlanePitch())));
00146
00147 createTransform(src.getSize(),
00148 vars,
00149 (Lens::LensProjectionFormat) src.getProjection(),
00150 dest.getSize(),
00151 dest.getProjection(),
00152 dest.getProjectionParameters(),
00153 dest.getHFOV(),
00154 src.getSize());
00155 }
00156
00157
00158 void Transform::createTransform(const vigra::Diff2D & srcSize,
00159 VariableMap srcVars,
00160 Lens::LensProjectionFormat srcProj,
00161 const vigra::Diff2D &destSize,
00162 PanoramaOptions::ProjectionFormat destProj,
00163 const std::vector<double> & destProjParam,
00164 double destHFOV,
00165 const vigra::Diff2D & originalSrcSize)
00166 {
00167 m_srcTX = destSize.x/2.0;
00168 m_srcTY = destSize.y/2.0;
00169
00170 m_destTX = srcSize.x/2.0;
00171 m_destTY = srcSize.y/2.0;
00172
00173
00174 if (originalSrcSize.x != 0 && originalSrcSize.y != 0) {
00175 double rx = srcSize.x / (double)originalSrcSize.x;
00176 double ry = srcSize.y / (double)originalSrcSize.y;
00177 map_get(srcVars,"d").setValue( map_get(srcVars,"d").getValue() * rx );
00178 map_get(srcVars,"e").setValue( map_get(srcVars,"e").getValue() * ry );
00179 }
00180
00181 updatePTData(srcSize, srcVars, srcProj,
00182 destSize, destProj, destProjParam, destHFOV);
00183
00184 SetMakeParams( m_stack, &m_mp, &m_srcImage , &m_dstImage, 0 );
00185 }
00186
00187
00188 void Transform::createInvTransform(const PanoramaData & pano, unsigned int imgNr,
00189 const PanoramaOptions & dest, vigra::Diff2D srcSize)
00190 {
00191 const SrcPanoImage & img = pano.getImage(imgNr);
00192 if (srcSize.x == 0 && srcSize.y == 0) {
00193 srcSize.x = img.getWidth();
00194 srcSize.y = img.getHeight();
00195 }
00196 createInvTransform(srcSize,
00197 pano.getImageVariables(imgNr),
00198 (Lens::LensProjectionFormat)pano.getImage(imgNr).getProjection(),
00199 vigra::Diff2D(dest.getWidth(), dest.getHeight()),
00200 dest.getProjection(),
00201 dest.getProjectionParameters(),
00202 dest.getHFOV(),
00203 vigra::Diff2D(img.getWidth(), img.getHeight()));
00204 }
00205
00206 void Transform::createInvTransform(const vigra::Diff2D & srcSize,
00207 VariableMap srcVars,
00208 Lens::LensProjectionFormat srcProj,
00209 const vigra::Diff2D & destSize,
00210 PanoramaOptions::ProjectionFormat destProj,
00211 const std::vector<double> & destProjParam,
00212 double destHFOV,
00213 const vigra::Diff2D & originalSrcSize)
00214 {
00215 m_srcTX = srcSize.x/2.0;
00216 m_srcTY = srcSize.y/2.0;
00217
00218 m_destTX = destSize.x/2.0;
00219 m_destTY = destSize.y/2.0;
00220
00221
00222 if (originalSrcSize.x != 0 && originalSrcSize.y != 0) {
00223 double rx = srcSize.x / (double)originalSrcSize.x;
00224 double ry = srcSize.y / (double)originalSrcSize.y;
00225 map_get(srcVars,"d").setValue( map_get(srcVars,"d").getValue() * rx );
00226 map_get(srcVars,"e").setValue( map_get(srcVars,"e").getValue() * ry );
00227 }
00228
00229 updatePTData(srcSize, srcVars, srcProj,
00230 destSize, destProj,
00231 destProjParam,
00232 destHFOV);
00233
00234 SetInvMakeParams( m_stack, &m_mp, &m_srcImage , &m_dstImage, 0 );
00235 }
00236
00237
00238 bool Transform::transform(double & x_dest, double & y_dest,
00239 double x_src, double y_src) const
00240 {
00241 void * params= (void *) (&m_stack);
00242 return execute_stack_new(x_src, y_src, &x_dest, &y_dest, params) != 0;
00243 }
00244
00246 bool Transform::transform(hugin_utils::FDiff2D& dest, const hugin_utils::FDiff2D & src) const
00247 {
00248 double x_dest, y_dest;
00249 void * params= (void *) (&m_stack);
00250 bool ok = execute_stack_new(src.x, src.y, &x_dest, &y_dest, params) != 0;
00251 dest.x = x_dest;
00252 dest.y = y_dest;
00253 return ok;
00254 }
00255
00259 bool Transform::transformImgCoord(double & x_dest, double & y_dest,
00260 double x_src, double y_src) const
00261 {
00262 x_src -= m_srcTX - 0.5 ;
00263 y_src -= m_srcTY - 0.5;
00264
00265 void * params= (void *) (&m_stack);
00266 bool ok = execute_stack_new(x_src, y_src, &x_dest, &y_dest, params) != 0;
00267 if(ok)
00268 {
00269 x_dest += m_destTX - 0.5;
00270 y_dest += m_destTY - 0.5;
00271 }
00272 else
00273 {
00274
00275
00276
00277
00278 x_dest = -1;
00279 y_dest = -1;
00280 };
00281 return ok;
00282 }
00283
00284
00285 VariableMapVector GetAlignInfoVariables(const AlignInfo& gl)
00286 {
00287 VariableMapVector res;
00288 if (gl.im) {
00289 for (int i = 0; i < gl.numIm; i++) {
00290 VariableMap vars;
00291 vars.insert(make_pair(std::string("TrX"), Variable("TrX", gl.im[i].cP.trans_x)));
00292 vars.insert(make_pair(std::string("TrY"), Variable("TrY", gl.im[i].cP.trans_y)));
00293 vars.insert(make_pair(std::string("TrZ"), Variable("TrZ", gl.im[i].cP.trans_z)));
00294 vars.insert(make_pair(std::string("Tpy"), Variable("Tpy", gl.im[i].cP.trans_yaw)));
00295 vars.insert(make_pair(std::string("Tpp"), Variable("Tpp", gl.im[i].cP.trans_pitch)));
00296
00297 vars.insert(make_pair(std::string("v"), Variable("v", gl.im[i].hfov)));
00298 vars.insert(make_pair(std::string("y"), Variable("y", gl.im[i].yaw)));
00299 vars.insert(make_pair(std::string("r"), Variable("r", gl.im[i].roll)));
00300 vars.insert(make_pair(std::string("p"), Variable("p", gl.im[i].pitch)));
00301 vars.insert(make_pair(std::string("a"), Variable("a", gl.im[i].cP.radial_params[0][3])));
00302 vars.insert(make_pair(std::string("b"), Variable("b", gl.im[i].cP.radial_params[0][2])));
00303 vars.insert(make_pair(std::string("c"), Variable("c", gl.im[i].cP.radial_params[0][1])));
00304
00305 vars.insert(make_pair(std::string("e"), Variable("e", gl.im[i].cP.vertical_params[0])));
00306 vars.insert(make_pair(std::string("d"), Variable("d", gl.im[i].cP.horizontal_params[0])));
00307
00308
00309 vars.insert(make_pair(std::string("g"), Variable("g", gl.im[i].cP.shear_x)));
00310 vars.insert(make_pair(std::string("t"), Variable("t", gl.im[i].cP.shear_y)));
00311
00312
00313 res.push_back(vars);
00314 }
00315 }
00316 return res;
00317 }
00318
00319 CPVector GetAlignInfoCtrlPoints(const AlignInfo& gl)
00320 {
00321 CPVector result;
00322 if (gl.cpt) {
00323 for (int i = 0; i < gl.numPts; i++) {
00324 ControlPoint pnt(gl.cpt[i].num[0], gl.cpt[i].x[0], gl.cpt[i].y[0],
00325 gl.cpt[i].num[1], gl.cpt[i].x[1], gl.cpt[i].y[1], (ControlPoint::OptimizeMode) gl.cpt[i].type);
00326 pnt.error = sqrt(distSquared(i));
00327 result.push_back(pnt);
00328 }
00329 }
00330 return result;
00331 }
00332
00333
00334 void setDestImage(Image & image, vigra::Diff2D size,
00335 unsigned char * imageData,
00336 const PanoramaOptions::ProjectionFormat & format,
00337 const std::vector<double> & projParams,
00338 double destHFOV)
00339 {
00340 SetImageDefaults(&image);
00341 image.width = size.x;
00342 image.height = size.y;
00343 image.bytesPerLine = image.width*3;
00344 image.bitsPerPixel = 24;
00345 image.dataSize = image.height * image.bytesPerLine;
00346
00347
00348
00349
00350
00351 image.data = 0;
00352 pano_projection_features projd;
00353 if (panoProjectionFeaturesQuery((int) format, &projd)) {
00354 image.format = projd.internalFormat;
00355 } else {
00356 image.format = _equirectangular;
00357 PrintError("unsupported projection");
00358 }
00359 image.formatParamCount = projd.numberOfParameters;
00360 assert(image.formatParamCount == (int) projParams.size());
00361 for (int i=0; i < projd.numberOfParameters; i++) {
00362 image.formatParam[i] = projParams[i];
00363 DEBUG_DEBUG("projection parameter " << i << ": " << image.formatParam[i]);
00364 }
00365 image.hfov = destHFOV;
00366 }
00367
00368
00369
00370 void initCPrefs(cPrefs & p, const VariableMap &vars)
00371 {
00372 SetCorrectDefaults(&p);
00373
00374 double val;
00375 double a = const_map_get(vars,"a").getValue();
00376 double b = const_map_get(vars,"b").getValue();
00377 double c = const_map_get(vars,"c").getValue();
00378 if (a != 0.0 || b != 0.0 || c != 0) {
00379 p.radial = 1;
00380 p.radial_params[0][3] = p.radial_params[1][3] = p.radial_params[2][3] = a;
00381 p.radial_params[0][2] = p.radial_params[1][2] = p.radial_params[2][2] = b;
00382 p.radial_params[0][1] = p.radial_params[1][1] = p.radial_params[2][1] = c;
00383 double d = 1.0 - (a+b+c);
00384 p.radial_params[0][0] = p.radial_params[1][0] = p.radial_params[2][0] = d;
00385 } else {
00386 p.radial = 0;
00387 }
00388
00389 val = const_map_get(vars,"e").getValue();
00390 if (val != 0.0) {
00391 p.vertical = TRUE;
00392 p.vertical_params[0] = p.vertical_params[1] = p.vertical_params[2] = val;
00393 } else {
00394 p.vertical = FALSE;
00395 p.vertical_params[0] = p.vertical_params[1] = p.vertical_params[2] = 0;
00396 }
00397
00398 val = const_map_get(vars,"d").getValue();
00399 if (val != 0.0) {
00400 p.horizontal = TRUE;
00401 p.horizontal_params[0] = p.horizontal_params[1] = p.horizontal_params[2] = val;
00402 } else {
00403 p.horizontal = FALSE;
00404 p.horizontal_params[0] = p.horizontal_params[1] = p.horizontal_params[2] = 0;
00405 }
00406
00407 p.trans_x = const_map_get(vars,"TrX").getValue();
00408 p.trans_y = const_map_get(vars,"TrY").getValue();
00409 p.trans_z = const_map_get(vars,"TrZ").getValue();
00410 if (p.trans_x != 0 || p.trans_y != 0 || p.trans_z != 0)
00411 {
00412 p.trans = TRUE;
00413 p.trans_yaw = const_map_get(vars,"Tpy").getValue();
00414 p.trans_pitch = const_map_get(vars,"Tpp").getValue();
00415 }
00416 else
00417 {
00418 p.trans = FALSE;
00419 p.trans_yaw = 0;
00420 p.trans_pitch = 0;
00421 }
00422
00423
00424
00425 val = const_map_get(vars, "g").getValue();
00426 double val2 = const_map_get(vars, "t").getValue();
00427 if (val2 != 0.0 || val != 0.0) {
00428 p.shear = TRUE;
00429 p.shear_x = val;
00430 p.shear_y = val2;
00431 } else {
00432 p.shear = FALSE;
00433 }
00434 p.resize = FALSE;
00435 p.luminance = FALSE;
00436 p.cutFrame = FALSE;
00437 p.fourier = FALSE;
00438
00439
00440 SetCorrectionRadius(&p);
00441
00442 }
00443
00444 void setFullImage(Image & image, vigra::Diff2D size,
00445 unsigned char * imageData, const VariableMap & vars,
00446 const Lens::LensProjectionFormat format,
00447 bool correctDistortions)
00448 {
00449 SetImageDefaults(&image);
00450 image.width = size.x;
00451 image.height = size.y;
00452 image.bytesPerLine = image.width*3;
00453 image.bitsPerPixel = 24;
00454 image.dataSize = image.height * image.bytesPerLine;
00455
00456 #if 0
00457
00458 image.data = (unsigned char**)malloc( sizeof(unsigned char*) );
00459 if(image.data == NULL) {
00460 DEBUG_FATAL("Out of memory");
00461 }
00462 *(image.data) = imageData;
00463 #else
00464 image.data = 0;
00465 #endif
00466
00467 image.dataformat = _RGB;
00468 switch (format) {
00469 case BaseSrcPanoImage::RECTILINEAR:
00470 image.format = _rectilinear;
00471 break;
00472 case BaseSrcPanoImage::PANORAMIC:
00473 image.format = _panorama;
00474 break;
00475 case BaseSrcPanoImage::CIRCULAR_FISHEYE:
00476 image.format = _fisheye_circ;
00477 break;
00478 case BaseSrcPanoImage::FULL_FRAME_FISHEYE:
00479 image.format = _fisheye_ff;
00480 break;
00481 case BaseSrcPanoImage::EQUIRECTANGULAR:
00482 image.format = _equirectangular;
00483 break;
00484 case BaseSrcPanoImage::FISHEYE_ORTHOGRAPHIC:
00485 image.format = _orthographic;
00486 break;
00487 case BaseSrcPanoImage::FISHEYE_STEREOGRAPHIC:
00488 image.format = _stereographic;
00489 break;
00490 case BaseSrcPanoImage::FISHEYE_EQUISOLID:
00491 image.format = _equisolid;
00492 break;
00493 case BaseSrcPanoImage::FISHEYE_THOBY:
00494 image.format = _thoby;
00495 }
00496 image.hfov = const_map_get(vars,"v").getValue();
00497 image.yaw = const_map_get(vars,"y").getValue();
00498 image.pitch = const_map_get(vars,"p").getValue();
00499 image.roll = const_map_get(vars,"r").getValue();
00500
00501
00502 if (correctDistortions) {
00503 initCPrefs(image.cP,vars);
00504 }
00505
00506
00507 image.name[0]=0;
00508
00509 image.selection.top = 0;
00510 image.selection.left = 0;
00511 image.selection.right = image.width;
00512 image.selection.bottom = image.height;
00513 }
00514
00515
00516
00517
00518
00519
00520 void createAdjustTrform(TrformStr & trf)
00521 {
00522 trf.src = (Image *) malloc(sizeof(Image));
00523 SetImageDefaults(trf.src);
00524 trf.dest = (Image *) malloc(sizeof(Image));
00525 SetImageDefaults(trf.dest);
00526 trf.success = TRUE;
00527 trf.tool = _adjust;
00528 trf.mode = _destSupplied | _honor_valid;
00529 trf.data = 0;
00530 trf.interpolator = _nn;
00531 trf.gamma = 1.0;
00532 }
00533
00534
00535 void freeImage(Image &img)
00536 {
00537 if (img.data) {
00538 myfree((void**)img.data);
00539 }
00540 }
00541
00542 }}