a `§»e¸ã@sddlZddlZddlZddlZddlZddlZddlmZddl m Z m Z m Z ddl Z ddl mZddl mZddl mZddlmZddlZddl mZdd lmZdd lmZdd lmZgd ¢Zd d„Zdd„Zdd„Zdd„Z Gdd„de!ƒZ"Gdd„dƒZ#Gdd„dƒZ$dS)éN)Ú string_types)ÚdatetimeÚ timedeltaÚtimezone)Úio)Úlog)Úsystem)Úget_rolling_shutter_readout)Úget_image_size)Ú ExpatError)Ú sensor_data)Ú ecef_from_lla)Ú perspectiveÚfisheyeÚfisheye_opencvÚbrownÚdualÚequirectangularÚ sphericalcCsPd}d}|D]>}|jdus |jdur&q |j|j}||kr |}|j|jf}q |S©Nr©ÚwidthÚheight)ÚphotosZmax_mpÚmax_dimsÚpÚmp©rú/code/opendm/photo.pyÚfind_largest_photo_dimss rcCs2d}|D]$}|jdurqt|t|j|jƒƒ}q|Sr)rÚmaxr)rÚmax_dimrrrrÚfind_largest_photo_dim&s  r"cCs>d}d}|D],}|jdurq |j|j}||kr |}|}q |Srr)rZmax_pZmax_arearZarearrrÚfind_largest_photo/s  r#cCsH|dkr dS|dkrdS|dkr$dS|dkr0dSt d  |¡¡d Sd S) zñLength of a resolution unit in millimeters. Uses the values from the EXIF specs in https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html Args: resolution_unit: the resolution unit value given in the EXIF égffffff9@éé ééégü©ñÒMbP?z&Unknown EXIF resolution unit value: {}N)rÚ ODM_WARNINGÚformat)Úresolution_unitrrrÚget_mm_per_unit=s r-c@s eZdZdS)ÚPhotoCorruptedExceptionN)Ú__name__Ú __module__Ú __qualname__rrrrr.Rsr.c@seZdZdd„ZdS)Ú GPSRefMockcCs |g|_dS©N)Úvalues)ÚselfÚrefrrrÚ__init__VszGPSRefMock.__init__N)r/r0r1r7rrrrr2Usr2c@sleZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z dd„Z d[dd„Z dd„Z dd„Z dd„Zdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„Zd)d*„Zd+d,„Zd-d.„Zd/d0„Zd1d2„Zd3d4„Zd5d6„Zd7d8„Zd9d:„Zd;d<„Z d=d>„Z!d?d@„Z"dAdB„Z#dCdD„Z$dEdF„Z%dGdH„Z&d\dKdL„Z'dMdN„Z(dOdP„Z)dQdR„Z*dSdT„Z+dUdV„Z,dWdX„Z-dYdZ„Z.dS)]Ú ODM_Photoz ODMPhoto - a class for ODMPhotoscCs*tj |¡|_d|_d|_d|_d|_d|_d|_ d|_ d|_ d|_ d|_ d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_ d|_!d|_"d|_#d|_$d|_%d|_&d|_'d|_(d|_)d|_*d|_+d|_,d|_-d|_.d|_/d|_0| 1|¡dS)NÚr(ÚRGBrrç333333ë?)2ÚosÚpathÚbasenameÚfilenameÚmaskrrÚ camera_makeÚ camera_modelÚ orientationÚlatitudeÚ longitudeÚaltitudeÚ band_nameÚ band_indexÚ capture_uuidÚfnumberÚradiometric_calibrationÚ black_levelÚgainÚgain_adjustmentÚ exposure_timeÚ iso_speedÚbits_per_sampleÚvignetting_centerÚvignetting_polynomialÚspectral_irradianceÚhorizontal_irradianceÚirradiance_scale_to_siÚutc_timeÚyawÚpitchÚrollÚomegaÚphiÚkappaÚ sun_sensorÚdls_yawÚ dls_pitchÚdls_rollÚspeed_xÚspeed_yÚspeed_zÚ exif_widthÚ exif_heightÚ gps_xy_stddevÚ gps_z_stddevÚcamera_projectionÚ focal_ratioÚparse_exif_values)r5Ú path_filerrrr7]s^zODM_Photo.__init__c Cs0d |j|j|j|j|j|j|j|j|j |j ¡ S)NzV{} | camera: {} {} | dimensions: {} x {} | lat: {} | lon: {} | alt: {} | band: {} ({})) r+r?rArBrrrDrErFrGrH©r5rrrÚ__str__©sþzODM_Photo.__str__cCs ||_dSr3)r@)r5r@rrrÚset_mask®szODM_Photo.set_maskcCsz|j|_|j|_|j|_|jdurf|jdurf|jdurf|j|_|j|_|j|_|j|_ |j|_ |j|_ |j |_ |j|_dSr3)ÚyrDÚxrEÚzrFrXrYrZr_r`raZhorizontal_accuracyrgZvertical_accuracyrh)r5Z geo_entryrrrÚupdate_with_geo_entry±szODM_Photo.update_with_geo_entryc CsÚ t d¡ tj¡zt |¡\|_|_Wn0tyX}ztt |ƒƒ‚WYd}~n d}~00i}i}t |dƒÄ}t j |ddd}zÄd|vrÌz|dj |_|j ¡|_Wn"tyÊt d¡d|_Yn0d |vrz|d j |_|j ¡|_Wn$tyt d ¡d|_Yn0d |vrr| |d ¡|_d |vrr| |d ¡durr| |d ¡d krr|jd9_d|vržd|vrž| |d|d¡|_n0d|vrÎt d|j¡| |dtdƒ¡|_d|vrúd|vrú| |d|d¡|_n0d|vr*t d|j¡| |dtdƒ¡|_d|vrD| |d¡|_WnBttfyˆ}z$t d|jt |ƒf¡WYd}~n d}~00z0d|vrª| |d¡|_ n6d|vrÆ| |d¡|_ nd|vrà| |d¡|_ d|vrú| |d¡|_!d|vr| |d¡|_"d|vr0| |d¡|_#n6d|vrL| |d¡|_#nd |vrf| |d ¡|_#d!|vr€| |d!¡|_$d"|vr8|d"j }t% &|d#¡}d }d$|vr¼| |d$¡}d%} |d krÖd&} |d&9}t'd' (t)|ƒ¡ƒ}|| 9}|d(} |t*| d)7}t+ ,d*¡} |  -t% .d ¡¡} |  -|¡|  /¡d(|_0d+|vr†d,|vr†d-|vr†| |d+¡|_1| |d,¡|_2| |d-¡|_3d.|vrºd/|vrº| |d.¡|_4| |d/¡|_5Wn>tyú}z$t d0|jt |ƒf¡WYd}~n d}~00|jdur<|jd kr<|jdur<|jd krg¡| ;d?|d@gt'¡| ;dA|dBgt'¡| ;dC|dDgt'¡| ;dE|dFdGgt'¡| ;dH|gdI¢¡| ;dJ|dKgt'¡| ;dL|dMgt'¡|jd4krh| ;dN|dOg¡|jd4kr„| ;dP|dQg¡| ;dR|dSgt'¡| ;dT|dUgt'¡| ;dV|dWgt'¡dX|vrt'| 8|dX¡ƒ}t'| 8|dY¡ƒ}t<||ƒ|_=dZ|vr6t'| 8|dZ¡ƒ|_>n(| ;d[|d\d]gt'¡| ;d^|d_d`gt'¡da|vrŠdb|vrŠdc|vrŠ| ;dd|dagt'¡| ;de|dbgt'¡| ;df|dcgt'¡|j=dur¤|j=dg9_=|j>dur¾|j>dg9_>dh|vrþ| ;di|dhgt'¡| ;dj|dkgt'¡| ;dl|dmgt'¡| 8|dndog¡}|dur^| ?¡}|dpkrN|j ?¡dqkrN|j ?¡drkrNds}|t@vr^||_A| ;dt|gdu¢t'¡| ;dv|gdw¢t'¡| ;dx|gdy¢t'¡| B¡rÞ|j ?¡dzvrÀd{|jC|_C|j ?¡d|krÞ|jDd9_DWn>t y}z$t d}|jt |ƒf¡WYd}~n d}~00qTWdƒn1 s:0Y|j ?¡d~k r°|j ?¡dk r°tE Fd€|jtEjG¡}| r°dd‚dƒd„d…œ}| Hd†¡|_I| J| Hd‡¡| Hd‡¡¡|_:tE Kdˆd4|j:¡|_:| L||¡| M¡dS)‰NÚexifreadÚrbTF)ÚdetailsZextract_thumbnailz Image Makez"EXIF Image Make might be corruptedÚunknownz Image Modelz#EXIF Image Model might be corruptedzGPS GPSAltitudezGPS GPSAltitudeRefréÿÿÿÿzGPS GPSLatitudezGPS GPSLatitudeRefzRGPS position for %s might be incorrect, GPSLatitudeRef tag is missing (assuming N)ÚNzGPS GPSLongitudezGPS GPSLongitudeRefzSGPS position for %s might be incorrect, GPSLongitudeRef tag is missing (assuming E)ÚEzImage Orientationz&Cannot read basic EXIF tags for %s: %szImage Tag 0xC61AZ BlackLevelzImage BlackLevelzEXIF ExposureTimez EXIF FNumberz EXIF ISOSpeedzEXIF PhotographicSensitivityzEXIF ISOSpeedRatingszImage BitsPerSamplezEXIF DateTimeOriginalz%Y:%m:%d %H:%M:%SzEXIF SubSecTimeçð?gð¿z0.{}ç@@)Z millisecondsÚUTCzMakerNote SpeedXzMakerNote SpeedYzMakerNote SpeedZzEXIF ExifImageWidthzEXIF ExifImageLengthz)Cannot read extended EXIF tags for %s: %sz-%s has GPS position (0,0), possibly corrupted)zCamera:BandNamez@Camera:BandNamez FLIR:BandNameÚ r9rH)z DLS:SensorIdz@Camera:RigCameraIndexzCamera:RigCameraIndexrKz MicaSense:RadiometricCalibrationrRzCamera:VignettingCenterzSentera:VignettingCenterrSzCamera:VignettingPolynomialzSentera:VignettingPolynomialrUzCamera:HorizontalIrradiancerVzCamera:IrradianceScaleToSIUnitsr^zCamera:SunSensorrTzCamera:SpectralIrradiancezCamera:IrradiancerI)z@drone-dji:CaptureUUIDzMicaSense:CaptureIdz@Camera:ImageUniqueIDz@Camera:CaptureUUIDrMz@drone-dji:SensorGainrNz@drone-dji:SensorGainAdjustmentrAz @tiff:MakerBz @tiff:ModelrEz@drone-dji:LongituderDz@drone-dji:LatituderFz@drone-dji:AbsoluteAltitudez@drone-dji:RtkStdLonz@drone-dji:RtkStdLatz@drone-dji:RtkStdHgtrgz@Camera:GPSXYAccuracyZ GPSXYAccuracyrhz@Camera:GPSZAccuracyZ GPSZAccuracyz@drone-dji:FlightXSpeedz@drone-dji:FlightYSpeedz@drone-dji:FlightZSpeedrbrcrdg@zDLS:Yawr_r`z DLS:PitchrazDLS:Rollz@Camera:ModelTypezCamera:ModelTyperZparrotZsequoiarrX)z@drone-dji:FlightYawDegreez @Camera:Yawz Camera:YawrY)z@drone-dji:GimbalPitchDegreez @Camera:Pitchz Camera:PitchrZ)z@drone-dji:GimbalRollDegreez @Camera:Rollz Camera:Roll)ZdjiZ hasselbladéZZsenseflyzCannot read XMP tags for %s: %sZ aerovironmentZquantixzIMG_(\d+)_(\w+)\.\w+ZGreenZNirZRedZ RedGreenBlue)ZGRNZNIRZREDr:r(r$z [^A-Za-z0-9]+)NÚloggingÚ getLoggerÚsetLevelÚCRITICALr rrÚ Exceptionr.ÚstrÚopenrtZ process_filer4rAÚstripÚUnicodeDecodeErrorrr*rBÚ float_valuerFÚ int_valueÚdms_to_decimalrDr?r2rErCÚ IndexErrorÚ ValueErrorÚ list_valuesrLrOrJrPrQrÚstrptimeÚfloatr+ÚintrÚpytzrZlocalizeÚutcfromtimestampÚ total_secondsrWrbrcrdrerfÚseekÚget_xmpÚ get_xmp_tagÚreplacerGÚset_attr_from_xmp_tagr rgrhÚlowerÚ projectionsriÚhas_yprrYrZÚreÚmatchÚ IGNORECASEÚgrouprIÚgetÚsubÚ compute_focalÚ compute_opk)r5Z _path_fileÚeÚtagsÚxtagsÚfZstr_timerWZsubsecÚnegativeÚmsrÚepochZxmprGrprqriÚmatchesZ band_aliasesrrrrk¿sö"         2   .                ÿþ ÿ.ÿÿ    ÿþþÿþÿþÿþþýÿþÿþ ÿ ÿÿþÿþÿþ   þýþý ÿþÿþÿþÿþ    *   R  ÿü  zODM_Photo.parse_exif_valuesc Cs`z| |j|j||¡|_Wn@ttfyZ}z$t d|jt |ƒf¡WYd}~n d}~00dS)Nz%Cannot extract focal ratio for %s: %s) Ú extract_focalrArBrjrŒrrr*r?r…)r5r¦r§r¥rrrr£êszODM_Photo.compute_focalcCs||dkr| |d¡}| ¡d| ¡ ¡ ¡}d}d|vr²d|vr²| |d¡}t|ƒ}|r²| |d¡} | dkrŠd|vrŠ| |d¡} | dkr²|jdur²d| } |j| |}d} d} d |vrÐ| |d ¡} d |vræ| |d ¡} | dur,d |vr,| |d g¡} t d t | ƒ¡}|r,t |  d¡ƒ} | durJ| dkrJ| d }n.|s^t ƒ  |d¡}|rt| rt| |}nd}|S)Nrwr9r~zEXIF FocalPlaneResolutionUnitzEXIF FocalPlaneXResolutionrzEXIF FocalPlaneYResolutionr(zEXIF FocalLengthIn35mmFilmzEXIF FocalLengthz @aux:Lensz ([\d\.]+)mmgB@r;)r˜r‡ršr‰r-rr—rÚsearchr…rr r r¡)r5ÚmakeÚmodelr¦r§Z sensor_stringZ sensor_widthr,Z mm_per_unitZpixels_per_unitZunits_per_pixelZfocal_35ZfocalZlensr¬rjrrrr­ðsB    zODM_Photo.extract_focalNcCs`| ||¡}|dur\|dur*t|||ƒn2|tks:|tkrLd|vrL| |¡}t||||ƒƒdS)Nú/)r—Úsetattrrr‘Útry_parse_fraction)r5ÚattrÚxmp_tagsr¦ÚcastÚvrrrr™s  zODM_Photo.set_attr_from_xmp_tagcCs¤t|tƒr|g}|D]Š}||vr||}t|tƒr>t|ƒSt|tƒr‚| di¡ di¡}|ržt|tƒrr|Sd |¡Sqt|tƒs–t|tƒr|SqdS)Nzrdf:Seqzrdf:lir~)Ú isinstancer…rÚdictr¡Újoinr‘r)r5rµr¦ÚtagÚtÚitemsrrrr—'s     zODM_Photo.get_xmp_tagc Csä| ¡}| d¡}| d¡}||krÜ|||d… d¡}zt |¡}WnXty }z@ddlm}t||dƒƒ}t |¡}t   d|j ¡WYd}~n d}~00|  d i¡}|  d i¡}|  d i¡}t |tƒrÔ|S|gSngSdS) Ns xóz(ODM_Photo.int_values..r9)r¸r4rÆr…r‘©r5r»rrrÚ int_valuesvs  zODM_Photo.int_valuescCs"| |¡}t|ƒdkr|dSdSr)rÛrÑrÕrrrrŠ~s  zODM_Photo.int_valuecCsd tt|jƒ¡S)Nr~)rºÚmapr…r4rÚrrrrŽƒszODM_Photo.list_valuescCsR| d¡}t|ƒdkrNz$tt|ƒ\}}|dkr6||n|WStyLYn0|S)Nr±r$r)ÚsplitrÑrÜrr)r5ÚvalÚpartsrÒrÎrrrr³†s   zODM_Photo.try_parse_fractioncCs:t|jtƒr2|j d¡}t|ƒdkr2ttt|ƒƒSgd¢S)Nr~r%)NNN)r¸rKr…rÝrÑrÆrÜr©r5rßrrrÚget_radiometric_calibrations    z%ODM_Photo.get_radiometric_calibrationcCs.|jr*t dd„|j d¡Dƒ¡}| ¡SdS)NcSsg|] }t|ƒ‘qSr)rrÖrrrrØšrÙz,ODM_Photo.get_dark_level..r~)rLÚnpÚarrayrÝÚmean)r5ZlevelsrrrÚget_dark_level˜szODM_Photo.get_dark_levelcCs$|jdur|jS|jr |jdSdS)NgY@)rMrPrmrrrÚget_gains zODM_Photo.get_gaincCs4|jr,|j d¡}t|ƒdkr,ttt|ƒƒSddgS)Nr~r$)rRrÝrÑrÆrÜrràrrrÚget_vignetting_center¤s   zODM_Photo.get_vignetting_centercCsF|jrB|j d¡}t|ƒdkrBttt|ƒƒ}|jdkr>| ¡|SdS)Nr~rZSentera)rSrÝrÑrÆrÜrrAÚreverse)r5rßÚcoeffsrrrÚget_vignetting_polynomial«s   z#ODM_Photo.get_vignetting_polynomialcCs|jrt |jdtj¡SdS)Niè)rWrÚ fromtimestamprÚutcrmrrrÚ get_utc_time·szODM_Photo.get_utc_timecCs>|jdur:|jdur:|jdkr:|jdkr:|j|j|jSdSr)rJrOrmrrrÚget_photometric_exposure»s(z"ODM_Photo.get_photometric_exposurecCsF|jdur(d}|jdur|j}|j|S|jdkrB|jdurB|jSdS)Nr{ÚDJI)rUrVrArT©r5ÚscalerrrÚget_horizontal_irradianceÀs   z#ODM_Photo.get_horizontal_irradiancecCs@|jdur|jdS|jdurrôrz&Cannot compute OPK angles, divider = 0r(r$)rœrÚmathÚradiansrXrYrZrârãÚcosÚsinrFr rDrEÚlinalgÚnormrr*ÚTÚcrossÚdotrËÚatan2r[Úasinr\r])r5rprÚrZcnbZcbbÚdeltaZaltÚp1Úp2ZxnpÚmZznpZynpZcenZcebrrrr¤`s6(xt0þ þ    &zODM_Photo.compute_opkcCsP|jdur$|jdur$|j|jdS|jdurH|jdurH|j|jdSdSdS)Ng€„.Arô)rerfrrrmrrrÚget_capture_megapixels•s z ODM_Photo.get_capture_megapixelscCs$|j ¡| ¡ko"|j ¡| ¡kSr3)rAršrB)r5r¯r°rrrÚ is_make_model¡szODM_Photo.is_make_model)N)Fr)/r/r0r1Ú__doc__r7rnrorsrkr£r­r™r—r–r‹rÉr‰rÛrŠrŽr³rárårærçrêrírîròrórõrùrúrûrýrþrrrrrœr r rr¤r r!rrrrr8Zs\L-,         25 r8)%r€rr<rrtÚnumpyrâÚsixrrrrr’ÚopendmrrrZopendm.rollingshutterr Z xmltodictrÄr Zxml.parsers.expatr Zopensfm.sensorsr Z opensfm.geor r›rr"r#r-r„r.r2r8rrrrÚs2