PanoToolsInterface.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
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     // fill our data into the Pano Tools structures.
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     // not very nice, but I don't like to change all the stuff in this file..
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     // not very nice, but I don't like to change all the stuff in this file..
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     // adjust parameters dependant on the image size.
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     // create the actual stack
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     // adjust parameters dependant on the image size.
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     // create the actual stack
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         // if the image coordinates could not transformed, e.g. this can happen 
00275         // with non-zero translation parameters, set the result to a point
00276         // outside the image (-1,-1)
00277         // better solution would be to evaluate the return value of transformImgCoord
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             //Modified by Dev 
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     // Allocate memory for pointer to pointer to image data
00347 //    image.data = (unsigned char**)malloc( sizeof(unsigned char*) );
00348 //    if(image.data == NULL) {
00349 //        DEBUG_FATAL("Out of memory");
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 // internal function, used by setFullImage() to set the distortion parameters
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     // FIXME add shear parameters
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     // calculate correction radius
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     // Allocate memory for pointer to pointer to image data
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     //fill cPrefs struct
00502     if (correctDistortions) {
00503         initCPrefs(image.cP,vars);
00504     }
00505 
00506     // no name
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 // prepare a Trform struct for the adjust operation, image -> pano
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 }} // namespace

Generated on 24 Oct 2014 for Hugintrunk by  doxygen 1.4.7