00001
00002
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <iostream>
00032 #include <stdio.h>
00033
00034
00035 #include "SrcPanoImage.h"
00036
00037 #include <iostream>
00038 #include <vector>
00039 #include <vigra/diff2d.hxx>
00040 #include <vigra/imageinfo.hxx>
00041 #include <hugin_utils/utils.h>
00042 #include <exiv2/exif.hpp>
00043 #include <exiv2/image.hpp>
00044 #include <exiv2/easyaccess.hpp>
00045 #include <lensdb/LensDB.h>
00046
00047 #ifdef __FreeBSD__
00048 #define log2(x) (log(x) / M_LN2)
00049 #endif
00050
00051 #include "ImageVariableTranslate.h"
00052
00053 namespace HuginBase {
00054
00055 using namespace hugin_utils;
00056
00057 void SrcPanoImage::resize(const vigra::Size2D & sz)
00058 {
00059
00060
00061 double scale = (double) sz.x / m_Size.getData().x;
00062
00063
00064 m_RadialDistortionCenterShift.setData(m_RadialDistortionCenterShift.getData() * scale);
00065 m_Shear.setData(m_Shear.getData() * scale);
00066
00067
00068
00069 switch (m_CropMode.getData())
00070 {
00071 case NO_CROP:
00072 m_CropRect.setData(vigra::Rect2D(sz));
00073 break;
00074 case CROP_RECTANGLE:
00075 m_CropRect.setData(m_CropRect.getData() * scale);
00076 m_CropRect.setData(m_CropRect.getData() & vigra::Rect2D(sz));
00077 break;
00078 case CROP_CIRCLE:
00079 m_CropRect.setData(m_CropRect.getData() * scale);
00080 break;
00081 }
00082
00083 m_Size = sz;
00084
00085 m_RadialVigCorrCenterShift.setData(m_RadialVigCorrCenterShift.getData() *scale);
00086
00087 MaskPolygonVector scaledMasks=m_Masks.getData();
00088 for(unsigned int i=0;i<scaledMasks.size();i++)
00089 scaledMasks[i].scale(scale);
00090 m_Masks.setData(scaledMasks);
00091 scaledMasks.clear();
00092 scaledMasks=m_ActiveMasks.getData();
00093 for(unsigned int i=0;i<scaledMasks.size();i++)
00094 scaledMasks[i].scale(scale);
00095 m_ActiveMasks.setData(scaledMasks);
00096 }
00097
00098 bool SrcPanoImage::horizontalWarpNeeded()
00099 {
00100 switch (m_Projection.getData())
00101 {
00102 case PANORAMIC:
00103 case EQUIRECTANGULAR:
00104 if (m_HFOV.getData() == 360) return true;
00105 case FULL_FRAME_FISHEYE:
00106 case CIRCULAR_FISHEYE:
00107 case RECTILINEAR:
00108 case FISHEYE_ORTHOGRAPHIC:
00109 case FISHEYE_STEREOGRAPHIC:
00110 case FISHEYE_EQUISOLID:
00111 case FISHEYE_THOBY:
00112 default:
00113 break;
00114 }
00115 return false;
00116 }
00117
00118 void BaseSrcPanoImage::setDefaults()
00119 {
00120
00121
00122
00123
00124 std::vector<double> distortion_default(4, 0.0);
00125 distortion_default[3] = 1;
00126
00127 std::vector<double> RadialVigCorrCoeff_default(4, 0.0);
00128 RadialVigCorrCoeff_default[0] = 1;
00129 HuginBase::MaskPolygonVector defaultMaskVector;
00130 #define image_variable( name, type, default_value ) m_##name.setData(default_value);
00131 #include "image_variables.h"
00132 #undef image_variable
00133 }
00134
00135 bool SrcPanoImage::isInside(vigra::Point2D p, bool ignoreMasks) const
00136 {
00137 bool insideCrop=false;
00138 switch(m_CropMode.getData()) {
00139 case NO_CROP:
00140 case CROP_RECTANGLE:
00141 insideCrop = m_CropRect.getData().contains(p);
00142 break;
00143 case CROP_CIRCLE:
00144 {
00145 if (0 > p.x || 0 > p.y || p.x >= m_Size.getData().x || p.y >= m_Size.getData().y) {
00146
00147 return false;
00148 }
00149 FDiff2D cropCenter;
00150 cropCenter.x = m_CropRect.getData().left() + m_CropRect.getData().width()/2.0;
00151 cropCenter.y = m_CropRect.getData().top() + m_CropRect.getData().height()/2.0;
00152 double radius2 = std::min(m_CropRect.getData().width()/2.0, m_CropRect.getData().height()/2.0);
00153 radius2 = radius2 * radius2;
00154 FDiff2D pf = FDiff2D(p) - cropCenter;
00155 insideCrop = (radius2 > pf.x*pf.x+pf.y*pf.y );
00156 }
00157 }
00158 if(insideCrop && !ignoreMasks)
00159 return !(isInsideMasks(p));
00160 else
00161 return insideCrop;
00162 }
00163
00164 bool SrcPanoImage::isCircularCrop() const
00165 {
00166 HuginBase::BaseSrcPanoImage::Projection projection=m_Projection.getData();
00167 return (projection==CIRCULAR_FISHEYE || projection==FISHEYE_THOBY || projection==FISHEYE_ORTHOGRAPHIC);
00168 };
00169
00170 bool SrcPanoImage::getCorrectTCA() const
00171 {
00172 bool nr = (m_RadialDistortionRed.getData()[0] == 0.0 && m_RadialDistortionRed.getData()[1] == 0.0 &&
00173 m_RadialDistortionRed.getData()[2] == 0.0 && m_RadialDistortionRed.getData()[3] == 1);
00174 bool nb = (m_RadialDistortionBlue.getData()[0] == 0.0 && m_RadialDistortionBlue.getData()[1] == 0.0 &&
00175 m_RadialDistortionBlue.getData()[2] == 0.0 && m_RadialDistortionBlue.getData()[3] == 1);
00176 return !(nr && nb);
00177 }
00178
00179
00180 FDiff2D SrcPanoImage::getRadialDistortionCenter() const
00181 { return FDiff2D(m_Size.getData())/2.0 + m_RadialDistortionCenterShift.getData(); }
00182
00183
00184 FDiff2D SrcPanoImage::getRadialVigCorrCenter() const
00185 { return (FDiff2D(m_Size.getData())-FDiff2D(1,1))/2.0 + m_RadialVigCorrCenterShift.getData(); }
00186
00187 void SrcPanoImage::setCropMode(CropMode val)
00188 {
00189 m_CropMode.setData(val);
00190 if (val == NO_CROP) {
00191 m_CropRect.setData(vigra::Rect2D(m_Size.getData()));
00192 }
00193 }
00194
00195 void SrcPanoImage::setSize(vigra::Size2D val)
00196 {
00197 m_Size.setData(val);
00198 if (m_CropMode.getData() == NO_CROP) {
00199 m_CropRect.setData(vigra::Rect2D(val));
00200 }
00201 }
00202
00203 double SrcPanoImage::getExposure() const
00204 { return 1.0/pow(2.0, m_ExposureValue.getData()); }
00205
00206 void SrcPanoImage::setExposure(const double & val)
00207 { m_ExposureValue = log2(1/val); }
00208
00209
00210 bool BaseSrcPanoImage::operator==(const BaseSrcPanoImage & other) const
00211 {
00212 DEBUG_TRACE("");
00213 return (
00214 #define image_variable( name, type, default_value ) \
00215 m_##name.getData() == other.m_##name.getData() &&
00216 #include "image_variables.h"
00217 #undef image_variable
00218 true
00219 );
00220 }
00221
00222
00223 double SrcPanoImage::getVar(const std::string & code) const
00224 {
00225 DEBUG_TRACE("");
00226 assert(code.size() > 0);
00227 #define image_variable( name, type, default_value ) \
00228 if (PTOVariableConverterFor##name::checkApplicability(code)) \
00229 return PTOVariableConverterFor##name::getValueFromVariable(code, m_##name );\
00230 else
00231 #include "image_variables.h"
00232 #undef image_variable
00233 {
00234 DEBUG_ERROR("Unknown variable " << code);
00235 }
00236 return 0;
00237 }
00238
00239 void SrcPanoImage::setVar(const std::string & code, double val)
00240 {
00241 DEBUG_TRACE("Var:" << code << " value: " << val);
00242 assert(code.size() > 0);
00243 #define image_variable( name, type, default_value ) \
00244 if (PTOVariableConverterFor##name::checkApplicability(code)) \
00245 {PTOVariableConverterFor##name::setValueFromVariable(code, m_##name, val);}\
00246 else
00247 #include "image_variables.h"
00248 #undef image_variable
00249 {
00250 DEBUG_ERROR("Unknown variable " << code);
00251 }
00252 }
00253
00254 VariableMap SrcPanoImage::getVariableMap() const
00255 {
00256
00257
00258
00259
00260 DEBUG_TRACE("");
00261
00262 VariableMap vars;
00263 #define image_variable( name, type, default_value ) \
00264 PTOVariableConverterFor##name::addToVariableMap(m_##name, vars);
00265 #include "image_variables.h"
00266 #undef image_variable
00267
00268 return vars;
00269 }
00270
00271 bool SrcPanoImage::readEXIF(double & focalLength, double & cropFactor, bool applyEXIFValues, bool applyExposureValue)
00272 {
00273 double eV=0;
00274 return readEXIF(focalLength,cropFactor,eV,applyEXIFValues, applyExposureValue);
00275 };
00276
00277 bool SrcPanoImage::readEXIF(double & focalLength, double & cropFactor, double & eV, bool applyEXIFValues, bool applyExposureValue)
00278 {
00279 std::string filename = getFilename();
00280 std::string ext = hugin_utils::getExtension(filename);
00281 std::transform(ext.begin(), ext.end(), ext.begin(), (int(*)(int)) toupper);
00282
00283 double roll = 0;
00284
00285 float isoSpeed = 0;
00286 float photoFNumber = 0;
00287 float exposureTime = 0;
00288 float subjectDistance = 0;
00289
00290 int width;
00291 int height;
00292 try {
00293 vigra::ImageImportInfo info(filename.c_str());
00294 width = info.width();
00295 height = info.height();
00296 } catch(std::exception & ) {
00297 return false;
00298 }
00299
00300
00301 setSize(vigra::Size2D(width, height));
00302 if (applyEXIFValues && focalLength > 0 && cropFactor > 0) {
00303 setHFOV(calcHFOV(getProjection(),
00304 focalLength, cropFactor, getSize()));
00305 }
00306
00307 Exiv2::Image::AutoPtr image;
00308 try {
00309 image = Exiv2::ImageFactory::open(filename.c_str());
00310 }catch(...) {
00311 std::cerr << __FILE__ << " " << __LINE__ << " Error opening file" << std::endl;
00312 return false;
00313 }
00314 if (image.get() == 0) {
00315 std::cerr << "Unable to open file to read EXIF data: " << filename << std::endl;
00316 return false;
00317 }
00318
00319 image->readMetadata();
00320 Exiv2::ExifData &exifData = image->exifData();
00321 if (exifData.empty()) {
00322 std::cerr << "Unable to read EXIF data from opened file:" << filename << std::endl;
00323 return false;
00324 }
00325
00326 getExiv2Value(exifData,"Exif.Photo.ExposureTime",exposureTime);
00327
00328
00329 getExiv2Value(exifData,"Exif.Photo.FNumber",photoFNumber);
00330
00331
00332 setExifAperture(photoFNumber);
00333
00334
00335 long exposureMode=0;
00336 getExiv2Value(exifData,"Exif.Photo.ExposureMode",exposureMode);
00337 setExifExposureMode((int)exposureMode);
00338
00339
00340
00341 if(photoFNumber==0)
00342 {
00343 photoFNumber=3.5;
00344 };
00345 if (exposureTime > 0 && photoFNumber > 0) {
00346 double gain = 1;
00347 if (getExiv2Value(exifData,"Exif.Photo.ISOSpeedRatings",isoSpeed)) {
00348 if (isoSpeed > 0) {
00349 gain = isoSpeed / 100.0;
00350 }
00351 }
00352 eV = log2(photoFNumber * photoFNumber / (gain * exposureTime));
00353 DEBUG_DEBUG ("Ev: " << eV);
00354 }
00355
00356 Exiv2::ExifKey key("Exif.Image.Make");
00357 Exiv2::ExifData::iterator itr = exifData.findKey(key);
00358 if (itr != exifData.end()) {
00359 setExifMake(itr->toString());
00360 } else {
00361 setExifMake("");
00362 }
00363
00364 Exiv2::ExifKey key2("Exif.Image.Model");
00365 itr = exifData.findKey(key2);
00366 if (itr != exifData.end()) {
00367 setExifModel(itr->toString());
00368 } else {
00369 setExifModel("");
00370 }
00371
00372
00373
00374
00375 std::string lensName;
00376 #if EXIV2_TEST_VERSION(0,22,0)
00377
00378 if(getExiv2Value(exifData,"Exif.Photo.LensModel",lensName))
00379 #else
00380 if(getExiv2Value(exifData,0xa434,"Photo",lensName))
00381 #endif
00382 {
00383 if(lensName.length()>0)
00384 {
00385 setExifLens(lensName);
00386 }
00387 else
00388 {
00389 setExifLens("");
00390 }
00391 }
00392 else
00393 {
00394
00395 Exiv2::ExifData::const_iterator itr2 = Exiv2::lensName(exifData);
00396 if (itr2!=exifData.end() && itr2->count())
00397 {
00398
00399
00400 setExifLens(itr2->print(&exifData));
00401 }
00402 else
00403 {
00404 setExifLens("");
00405 };
00406 };
00407
00408 long orientation = 0;
00409 if (getExiv2Value(exifData,"Exif.Image.Orientation",orientation) && trustExivOrientation()) {
00410 switch (orientation) {
00411 case 3:
00412 roll = 180;
00413 break;
00414 case 6:
00415 roll = 90;
00416 break;
00417 case 8:
00418 roll = 270;
00419 break;
00420 default:
00421 break;
00422 }
00423 }
00424
00425 long pixXdim = 0;
00426 getExiv2Value(exifData,"Exif.Photo.PixelXDimension",pixXdim);
00427
00428 long pixYdim = 0;
00429 getExiv2Value(exifData,"Exif.Photo.PixelYDimension",pixYdim);
00430
00431 if (pixXdim !=0 && pixYdim !=0 ) {
00432 double ratioExif = pixXdim/(double)pixYdim;
00433 double ratioImage = width/(double)height;
00434 if (fabs( ratioExif - ratioImage) > 0.1) {
00435
00436
00437 roll = 0;
00438 }
00439 }
00440
00441
00442
00443
00444
00445
00446
00447 long eWidth = 0;
00448 getExiv2Value(exifData,"Exif.Image.ImageWidth",eWidth);
00449
00450 long eLength = 0;
00451 getExiv2Value(exifData,"Exif.Image.ImageLength",eLength);
00452
00453 double sensorPixelWidth = 0;
00454 double sensorPixelHeight = 0;
00455 if (eWidth > 0 && eLength > 0) {
00456 sensorPixelHeight = (double)eLength;
00457 sensorPixelWidth = (double)eWidth;
00458 } else {
00459
00460 sensorPixelWidth = width;
00461 sensorPixelHeight = height;
00462 }
00463
00464
00465 if (sensorPixelWidth < sensorPixelHeight ) {
00466 double t = sensorPixelWidth;
00467 sensorPixelWidth = sensorPixelHeight;
00468 sensorPixelHeight = t;
00469 }
00470
00471 DEBUG_DEBUG("sensorPixelWidth: " << sensorPixelWidth);
00472 DEBUG_DEBUG("sensorPixelHeight: " << sensorPixelHeight);
00473
00474
00475
00476
00477 long exifResolutionUnits = 0;
00478 getExiv2Value(exifData,"Exif.Photo.FocalPlaneResolutionUnit",exifResolutionUnits);
00479
00480 float resolutionUnits= 0;
00481 switch (exifResolutionUnits) {
00482 case 3: resolutionUnits = 10.0; break;
00483 case 4: resolutionUnits = 1.0; break;
00484 case 5: resolutionUnits = .001; break;
00485 default: resolutionUnits = 25.4; break;
00486 }
00487
00488 DEBUG_DEBUG("Resolution Units: " << resolutionUnits);
00489
00490
00491
00492
00493 float fplaneXresolution = 0;
00494 getExiv2Value(exifData,"Exif.Photo.FocalPlaneXResolution",fplaneXresolution);
00495
00496 float fplaneYresolution = 0;
00497 getExiv2Value(exifData,"Exif.Photo.FocalPlaneYResolution",fplaneYresolution);
00498
00499 float CCDWidth = 0;
00500 if (fplaneXresolution != 0) {
00501
00502
00503 CCDWidth = (float)(sensorPixelWidth / ( fplaneXresolution / resolutionUnits));
00504 }
00505
00506 float CCDHeight = 0;
00507 if (fplaneYresolution != 0) {
00508 CCDHeight = (float)(sensorPixelHeight / ( fplaneYresolution / resolutionUnits));
00509 }
00510
00511 DEBUG_DEBUG("CCDHeight:" << CCDHeight);
00512 DEBUG_DEBUG("CCDWidth: " << CCDWidth);
00513
00514
00515 FDiff2D sensorSize;
00516
00517 if (CCDHeight > 0 && CCDWidth > 0) {
00518
00519 sensorSize.x = CCDWidth;
00520 sensorSize.y = CCDHeight;
00521 if (getExifModel() == "Canon EOS 20D") {
00522
00523 sensorSize.x = 22.5;
00524 sensorSize.y = 15;
00525 }
00526
00527
00528 double rsensor = (double)sensorSize.x / sensorSize.y;
00529 double rimg = (double) width / height;
00530 if ( (rsensor > 1 && rimg < 1) || (rsensor < 1 && rimg > 1) ) {
00531
00532
00533 float t;
00534 t = sensorSize.y;
00535 sensorSize.y = sensorSize.x;
00536 sensorSize.x = t;
00537 }
00538
00539 DEBUG_DEBUG("sensorSize.y: " << sensorSize.y);
00540 DEBUG_DEBUG("sensorSize.x: " << sensorSize.x);
00541
00542 cropFactor = sqrt(36.0*36.0+24.0*24.0) /
00543 sqrt(sensorSize.x*sensorSize.x + sensorSize.y*sensorSize.y);
00544
00545 if (cropFactor < 0.01 || cropFactor > 100) {
00546 cropFactor = 0;
00547 }
00548 } else {
00549
00550
00551
00552
00553
00554
00555
00556
00557 float olyFPD = 0;
00558 getExiv2Value(exifData,"Exif.Olympus.FocalPlaneDiagonal",olyFPD);
00559
00560 if (olyFPD > 0.0) {
00561
00562
00563
00564 cropFactor = sqrt(36.0*36.0+24.0*24.0) / olyFPD;
00565 }
00566 else {
00567
00568
00569 getExiv2Value(exifData,"Exif.OlympusEq.FocalPlaneDiagonal",olyFPD);
00570 if (olyFPD > 0.0) {
00571 cropFactor = sqrt(36.0*36.0+24.0*24.0) / olyFPD;
00572 };
00573 };
00574
00575 }
00576 DEBUG_DEBUG("cropFactor: " << cropFactor);
00577
00578 float eFocalLength = 0;
00579 getExiv2Value(exifData,"Exif.Photo.FocalLength",eFocalLength);
00580
00581 float eFocalLength35 = 0;
00582 getExiv2Value(exifData,"Exif.Photo.FocalLengthIn35mmFilm",eFocalLength35);
00583
00584
00585 if (eFocalLength > 0 && cropFactor > 0) {
00586
00587 focalLength = eFocalLength;
00588 } else if (eFocalLength35 > 0 && eFocalLength > 0) {
00589 cropFactor = eFocalLength35 / eFocalLength;
00590 focalLength = eFocalLength;
00591 } else if (eFocalLength35 > 0) {
00592
00593
00594 cropFactor = 1;
00595 focalLength = eFocalLength35;
00596 } else if (eFocalLength > 0 && cropFactor <= 0) {
00597
00598 focalLength = eFocalLength;
00599 cropFactor = 0;
00600 }
00601 getExiv2Value(exifData,"Exif.Photo.SubjectDistance", subjectDistance);
00602
00603 std::string captureDate;
00604 getExiv2Value(exifData,"Exif.Photo.DateTimeOriginal",captureDate);
00605
00606
00607
00608 setExifFocalLength(focalLength);
00609 setExifFocalLength35(eFocalLength35);
00610 setExifOrientation(roll);
00611 setExifISO(isoSpeed);
00612 setExifDistance(subjectDistance);
00613 setExifDate(captureDate);
00614 setExifExposureTime(exposureTime);
00615
00616 DEBUG_DEBUG("Results for:" << filename);
00617 DEBUG_DEBUG("Focal Length: " << getExifFocalLength());
00618 DEBUG_DEBUG("Crop Factor: " << getExifCropFactor());
00619 DEBUG_DEBUG("Roll: " << getExifOrientation());
00620
00621
00622 if (applyEXIFValues) {
00623 setRoll(roll);
00624 if (applyExposureValue)
00625 setExposureValue(eV);
00626 if(cropFactor>0)
00627 {
00628 setExifCropFactor(cropFactor);
00629 };
00630 if (focalLength > 0 && cropFactor > 0) {
00631 setHFOV(calcHFOV(getProjection(), focalLength, cropFactor, getSize()));
00632 DEBUG_DEBUG("HFOV: " << getHFOV());
00633 return true;
00634 } else {
00635 return false;
00636 }
00637 }
00638 return true;
00639 }
00640
00641 bool SrcPanoImage::readCropfactorFromDB()
00642 {
00643
00644 if(getExifCropFactor()<=0 && !getExifMake().empty() && !getExifModel().empty())
00645 {
00646 double dbCrop=0;
00647 if(LensDB::LensDB::GetSingleton().GetCropFactor(getExifMake(),getExifModel(),dbCrop))
00648 {
00649 if(dbCrop>0)
00650 {
00651 setExifCropFactor(dbCrop);
00652 return true;
00653 };
00654 };
00655 };
00656 return false;
00657 };
00658
00659 bool SrcPanoImage::readProjectionFromDB()
00660 {
00661 bool success=false;
00662 if(!getExifLens().empty())
00663 {
00664 LensDB::LensDB& lensDB=LensDB::LensDB::GetSingleton();
00665 if(lensDB.FindLens(getExifMake(), getExifModel(), getExifLens()))
00666 {
00667 Projection dbProjection;
00668 if(lensDB.GetProjection(dbProjection))
00669 {
00670 setProjection(dbProjection);
00671 success=true;
00672 };
00673 if(getExifFocalLength()>0)
00674 {
00675 CropMode dbCropMode;
00676 FDiff2D cropLeftTop;
00677 FDiff2D cropRightBottom;
00678 if(lensDB.GetCrop(getExifFocalLength(),dbCropMode,cropLeftTop,cropRightBottom))
00679 {
00680 switch(dbCropMode)
00681 {
00682 case NO_CROP:
00683 setCropMode(NO_CROP);
00684 break;
00685 case CROP_CIRCLE:
00686 if(isCircularCrop())
00687 {
00688 setCropMode(CROP_CIRCLE);
00689 int width=getSize().width();
00690 int height=getSize().height();
00691 if(width>height)
00692 {
00693 setCropRect(vigra::Rect2D(cropLeftTop.x*width,cropLeftTop.y*height,cropRightBottom.x*width,cropRightBottom.y*height));
00694 }
00695 else
00696 {
00697 setCropRect(vigra::Rect2D((1.0-cropRightBottom.y)*width,cropLeftTop.x*height,(1.0-cropLeftTop.y)*width,cropRightBottom.x*height));
00698 };
00699 };
00700 break;
00701 case CROP_RECTANGLE:
00702 if(!isCircularCrop())
00703 {
00704 int width=getSize().width();
00705 int height=getSize().height();
00706 setCropMode(CROP_RECTANGLE);
00707 if(width>height)
00708 {
00709 setCropRect(vigra::Rect2D(cropLeftTop.x*width,cropLeftTop.y*height,cropRightBottom.x*width,cropRightBottom.y*height));
00710 }
00711 else
00712 {
00713 setCropRect(vigra::Rect2D((1.0-cropRightBottom.y)*width,cropLeftTop.x*height,(1.0-cropLeftTop.y*width),cropRightBottom.x*height));
00714 };
00715 fprintf(stdout,"crop rect set: %f,%f-%f,%f \n",getCropRect().left(),getCropRect().top(),getCropRect().right(),getCropRect().bottom());
00716
00717 };
00718 break;
00719 };
00720 };
00721 };
00722 };
00723 };
00724 return success;
00725 };
00726
00727 bool SrcPanoImage::readDistortionFromDB()
00728 {
00729 bool success=false;
00730 if(!getExifLens().empty() || (!getExifMake().empty() && !getExifModel().empty()))
00731 {
00732 LensDB::LensDB& lensDB=LensDB::LensDB::GetSingleton();
00733 if(lensDB.FindLens(getExifMake(), getExifModel(), getExifLens()))
00734 {
00735 if(getExifFocalLength()>0)
00736 {
00737 std::vector<double> dist;
00738 if(lensDB.GetDistortion(getExifFocalLength(),dist))
00739 {
00740 if(dist.size()==3)
00741 {
00742 dist.push_back(1.0-dist[0]-dist[1]-dist[2]);
00743 setRadialDistortion(dist);
00744 success=true;
00745 };
00746 };
00747 };
00748 };
00749 };
00750 return success;
00751 };
00752
00753 bool SrcPanoImage::readVignettingFromDB()
00754 {
00755 bool success=false;
00756 if(!getExifLens().empty() || (!getExifMake().empty() && !getExifModel().empty()))
00757 {
00758 LensDB::LensDB& lensDB=LensDB::LensDB::GetSingleton();
00759 if(lensDB.FindLens(getExifMake(), getExifModel(), getExifLens()))
00760 {
00761 if(getExifFocalLength()>0)
00762 {
00763 std::vector<double> vig;
00764 if(lensDB.GetVignetting(getExifFocalLength(),getExifAperture(),getExifDistance(),vig))
00765 {
00766 setRadialVigCorrCoeff(vig);
00767 success=true;
00768 };
00769 };
00770 };
00771 };
00772 return success;
00773 };
00774
00775 double SrcPanoImage::calcHFOV(SrcPanoImage::Projection proj, double fl, double crop, vigra::Size2D imageSize)
00776 {
00777
00778 double d = sqrt(36.0*36.0 + 24.0*24.0) / crop;
00779 double r = (double)imageSize.x / imageSize.y;
00780
00781
00782
00783 FDiff2D sensorSize;
00784 sensorSize.x = d / sqrt(1 + 1/(r*r));
00785 sensorSize.y = sensorSize.x / r;
00786
00787 double hfov = 360;
00788
00789 switch (proj) {
00790 case SrcPanoImage::RECTILINEAR:
00791 hfov = 2*atan((sensorSize.x/2.0)/fl) * 180.0/M_PI;
00792 break;
00793 case SrcPanoImage::CIRCULAR_FISHEYE:
00794 case SrcPanoImage::FULL_FRAME_FISHEYE:
00795 hfov = sensorSize.x / fl * 180/M_PI;
00796 break;
00797 case SrcPanoImage::EQUIRECTANGULAR:
00798 case SrcPanoImage::PANORAMIC:
00799 hfov = (sensorSize.x / fl) / M_PI * 180;
00800 break;
00801 case SrcPanoImage::FISHEYE_ORTHOGRAPHIC:
00802 {
00803 double val=(sensorSize.x/2.0)/fl;
00804 double n;
00805 double frac=modf(val, &n);
00806 hfov = 2 * asin(frac) * 180.0/M_PI + n * 180.0;
00807 }
00808 break;
00809 case SrcPanoImage::FISHEYE_EQUISOLID:
00810 hfov = 4 * asin(std::min<double>(1.0, (sensorSize.x/4.0)/fl)) * 180.0/M_PI;
00811 break;
00812 case SrcPanoImage::FISHEYE_STEREOGRAPHIC:
00813 hfov = 4 * atan((sensorSize.x/4.0)/fl) * 180.0/M_PI;
00814 break;
00815 case SrcPanoImage::FISHEYE_THOBY:
00816 hfov = 2 * asin(std::min<double>(1.0, sensorSize.x/(2.0*fl*1.47))) * 180.0/M_PI/0.713;
00817 break;
00818 default:
00819 hfov = 360;
00820
00821 DEBUG_WARN("Focal length calculations only supported with rectilinear and fisheye images");
00822 }
00823 return hfov;
00824 }
00825
00826 double SrcPanoImage::calcFocalLength(SrcPanoImage::Projection proj, double hfov, double crop, vigra::Size2D imageSize)
00827 {
00828
00829 double d = sqrt(36.0*36.0 + 24.0*24.0) / crop;
00830 double r = (double)imageSize.x / imageSize.y;
00831
00832
00833
00834 FDiff2D sensorSize;
00835 sensorSize.x = d / sqrt(1 + 1/(r*r));
00836 sensorSize.y = sensorSize.x / r;
00837
00838 switch (proj)
00839 {
00840 case SrcPanoImage::RECTILINEAR:
00841 return (sensorSize.x/2.0) / tan(hfov/180.0*M_PI/2);
00842 break;
00843 case SrcPanoImage::CIRCULAR_FISHEYE:
00844 case SrcPanoImage::FULL_FRAME_FISHEYE:
00845
00846
00847 return sensorSize.x / (hfov/180*M_PI);
00848 break;
00849 case SrcPanoImage::EQUIRECTANGULAR:
00850 case SrcPanoImage::PANORAMIC:
00851 return (sensorSize.x / (hfov/180*M_PI));
00852 break;
00853 case SrcPanoImage::FISHEYE_ORTHOGRAPHIC:
00854 {
00855 int t=(int)ceil((hfov-180)/360);
00856 return (sensorSize.x /2.0) / (2 * t + pow ( -1.0, t) * sin(hfov/180.0*M_PI/2.0));
00857 };
00858 case SrcPanoImage::FISHEYE_STEREOGRAPHIC:
00859 return (sensorSize.x/4.0) / tan(hfov/180.0*M_PI/4.0);
00860 case SrcPanoImage::FISHEYE_EQUISOLID:
00861 return (sensorSize.x/4.0) / sin(hfov/180.0*M_PI/4.0);
00862 case SrcPanoImage::FISHEYE_THOBY:
00863 return (sensorSize.x/2.0) / (1.47 * sin(hfov/180.0*M_PI * 0.713 / 2.0));
00864 default:
00865
00866 DEBUG_WARN("Focal length calculations only supported with rectilinear and fisheye images");
00867 return 0;
00868 }
00869 }
00870
00871 double SrcPanoImage::calcCropFactor(SrcPanoImage::Projection proj, double hfov, double focalLength, vigra::Size2D imageSize)
00872 {
00873
00874 double r = (double)imageSize.x / imageSize.y;
00875
00876 double x = 36;
00877 switch (proj)
00878 {
00879 case SrcPanoImage::RECTILINEAR:
00880 x = focalLength * tan(hfov/180.0*M_PI/2);
00881 break;
00882 case SrcPanoImage::CIRCULAR_FISHEYE:
00883 case SrcPanoImage::FULL_FRAME_FISHEYE:
00884 case SrcPanoImage::EQUIRECTANGULAR:
00885 case SrcPanoImage::FISHEYE_ORTHOGRAPHIC:
00886 case SrcPanoImage::FISHEYE_STEREOGRAPHIC:
00887 case SrcPanoImage::FISHEYE_EQUISOLID:
00888 case SrcPanoImage::FISHEYE_THOBY:
00889 case SrcPanoImage::PANORAMIC:
00890
00891
00892 x = focalLength * (hfov/180*M_PI);
00893 break;
00894 default:
00895
00896 DEBUG_WARN("Focal length calculations only supported with rectilinear and fisheye images");
00897 return 0;
00898 }
00899
00900 double diag = x * sqrt(1+ 1/(r*r));
00901 return sqrt(36.0*36.0 + 24.0*24.0) / diag;
00902 }
00903
00904 void SrcPanoImage::updateFocalLength(double newFocalLength)
00905 {
00906 double newHFOV=calcHFOV(getProjection(),newFocalLength,getExifCropFactor(),getSize());
00907 if(newHFOV!=0)
00908 {
00909 setHFOV(newHFOV);
00910 };
00911 };
00912
00913 void SrcPanoImage::updateCropFactor(double focalLength, double newCropFactor)
00914 {
00915 double newHFOV=calcHFOV(getProjection(),focalLength,newCropFactor,getSize());
00916 if(newHFOV!=0)
00917 {
00918 setHFOV(newHFOV);
00919 };
00920 setExifCropFactor(newCropFactor);
00921 };
00922
00923
00924 bool SrcPanoImage::getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, long & value)
00925 {
00926 Exiv2::ExifKey key(keyName);
00927 Exiv2::ExifData::iterator itr = exifData.findKey(key);
00928 if (itr != exifData.end() && itr->count()) {
00929 value = itr->toLong();
00930 DEBUG_DEBUG("" << keyName << ": " << value);
00931 return true;
00932 } else {
00933 return false;
00934 }
00935 }
00936
00937
00938 bool SrcPanoImage::getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, float & value)
00939 {
00940 Exiv2::ExifKey key(keyName);
00941 Exiv2::ExifData::iterator itr = exifData.findKey(key);
00942 if (itr != exifData.end() && itr->count()) {
00943 value = itr->toFloat();
00944 DEBUG_DEBUG("" << keyName << ": " << value);
00945 return true;
00946 } else {
00947 return false;
00948 }
00949 }
00950
00951
00952 bool SrcPanoImage::getExiv2Value(Exiv2::ExifData& exifData, std::string keyName, std::string & value)
00953 {
00954 Exiv2::ExifKey key(keyName);
00955 Exiv2::ExifData::iterator itr = exifData.findKey(key);
00956 if (itr != exifData.end() && itr->count()) {
00957 value = itr->toString();
00958 DEBUG_DEBUG("" << keyName << ": " << value);
00959 return true;
00960 } else {
00961 return false;
00962 }
00963 }
00964
00965 bool SrcPanoImage::getExiv2Value(Exiv2::ExifData& exifData, uint16_t tagID, std::string groupName, std::string & value)
00966 {
00967 Exiv2::ExifKey key(tagID,groupName);
00968 Exiv2::ExifData::iterator itr = exifData.findKey(key);
00969 if (itr != exifData.end() && itr->count())
00970 {
00971 value = itr->toString();
00972 return true;
00973 }
00974 else
00975 {
00976 return false;
00977 }
00978 }
00979
00980
00981 void SrcPanoImage::addMask(MaskPolygon newMask)
00982 {
00983 MaskPolygonVector newMasks=m_Masks.getData();
00984 newMasks.push_back(newMask);
00985 setMasks(newMasks);
00986 };
00987
00988 void SrcPanoImage::addActiveMask(MaskPolygon newMask)
00989 {
00990 MaskPolygonVector newMasks=m_ActiveMasks.getData();
00991 newMasks.push_back(newMask);
00992 setActiveMasks(newMasks);
00993 };
00994
00995 void SrcPanoImage::clearActiveMasks()
00996 {
00997 MaskPolygonVector emptyMaskVector;
00998 m_ActiveMasks.setData(emptyMaskVector);
00999 };
01000
01001 bool SrcPanoImage::hasMasks() const
01002 {
01003 return m_Masks.getData().size()>0;
01004 };
01005
01006 bool SrcPanoImage::hasPositiveMasks() const
01007 {
01008 MaskPolygonVector masks=m_Masks.getData();
01009 if(masks.size()>0)
01010 {
01011 for(unsigned int i=0;i<masks.size();i++)
01012 {
01013 if(masks[i].isPositive())
01014 {
01015 return true;
01016 };
01017 };
01018 };
01019 return false;
01020 };
01021
01022 bool SrcPanoImage::hasActiveMasks() const
01023 {
01024 return m_ActiveMasks.getData().size()>0;
01025 };
01026
01027 void SrcPanoImage::printMaskLines(std::ostream &o, unsigned int newImgNr) const
01028 {
01029 if(m_Masks.getData().size()>0)
01030 for(unsigned int i=0;i<m_Masks.getData().size();i++)
01031 m_Masks.getData()[i].printPolygonLine(o, newImgNr);
01032 };
01033
01034 void SrcPanoImage::changeMaskType(unsigned int index, HuginBase::MaskPolygon::MaskType newType)
01035 {
01036 if(index<m_Masks.getData().size())
01037 {
01038 MaskPolygonVector editedMasks=m_Masks.getData();
01039 editedMasks[index].setMaskType(newType);
01040 m_Masks.setData(editedMasks);
01041 };
01042 };
01043
01044 void SrcPanoImage::deleteMask(unsigned int index)
01045 {
01046 if(index<m_Masks.getData().size())
01047 {
01048 MaskPolygonVector oldMasks=m_Masks.getData();
01049 oldMasks.erase(oldMasks.begin()+index);
01050 m_Masks.setData(oldMasks);
01051 };
01052 };
01053
01054 void SrcPanoImage::deleteAllMasks()
01055 {
01056 MaskPolygonVector emptyMaskVector;
01057 m_Masks.setData(emptyMaskVector);
01058 };
01059
01060 bool SrcPanoImage::isInsideMasks(vigra::Point2D p) const
01061 {
01062 if(!hasActiveMasks())
01063 return false;
01064 bool insideMask=false;
01065 unsigned int i=0;
01066 while(!insideMask && i<m_ActiveMasks.getData().size())
01067 {
01068 insideMask=m_ActiveMasks.getData()[i].isInside(p);
01069 i++;
01070 };
01071 return insideMask;
01072 };
01073
01080 bool SrcPanoImage::trustExivOrientation()
01081 {
01082 if(getSize().width() < getSize().height())
01083 return false;
01084
01085 return true;
01086 }
01087
01088 const int SrcPanoImage::getExifDateTime(struct tm* datetime) const
01089 {
01090
01091 std::memset(datetime, 0x0, sizeof(*datetime));
01092
01093 datetime->tm_isdst=-1;
01094 return Exiv2::exifTime(m_ExifDate.getData().c_str(),datetime);
01095 };
01096
01097 }