जनवरी 2009
मकसद
इस ट्यूटोरियल में, जियोटैग की गई फ़ोटो का इस्तेमाल करके KML PhotoOverlays बनाने का तरीका बताया गया है. सैंपल कोड को Python में लिखा गया है. हालांकि, ऐसी कई लाइब्रेरी अन्य प्रोग्रामिंग भाषाओं में भी मौजूद हैं. इसलिए, इस कोड को किसी दूसरी भाषा में अनुवाद करने में कोई समस्या नहीं होनी चाहिए. इस लेख में दिया गया कोड, ओपन सोर्स Python लाइब्रेरी EXIF.py पर आधारित है.
परिचय
डिजिटल कैमरे बहुत शानदार होते हैं. कई लोगों को इस बात का पता नहीं होता, लेकिन वे सिर्फ़ फ़ोटो और वीडियो लेने के अलावा और भी बहुत कुछ करते हैं. ये ऐप्लिकेशन, वीडियो और फ़ोटो को कैमरे और उसकी सेटिंग के मेटाडेटा के साथ टैग भी करते हैं. पिछले कुछ सालों में, लोगों ने उस जानकारी में भौगोलिक डेटा जोड़ने के तरीके खोज लिए हैं. यह डेटा, कैमरा बनाने वाली कंपनियां एम्बेड करती हैं. जैसे, Ricoh और Nikon के कुछ कैमरे. इसके अलावा, जीपीएस लॉगर और EyeFi Explore जैसे डिवाइसों से भी यह डेटा जोड़ा जा सकता है. iPhone जैसे कैमरा फ़ोन और Android ऑपरेटिंग सिस्टम का इस्तेमाल करने वाले फ़ोन, जैसे कि T-Mobile का G1, उस डेटा को अपने-आप एम्बेड कर देते हैं. Panoramio, Picasa वेब एल्बम, और Flickr जैसी कुछ फ़ोटो अपलोड करने वाली साइटें, जीपीएस डेटा को अपने-आप पार्स कर लेती हैं. साथ ही, इसका इस्तेमाल फ़ोटो को जियोटैग करने के लिए करती हैं. इसके बाद, आपको फ़ीड में वह डेटा वापस मिल जाएगा. लेकिन इसमें मज़ा कहां है? इस लेख में, उस डेटा को खुद पाने का तरीका बताया गया है.
Exif हेडर
किसी इमेज फ़ाइल में डेटा एम्बेड करने का सबसे सामान्य तरीका, एक्सचेंजेबल इमेज फ़ाइल फ़ॉर्मैट या EXIF़ का इस्तेमाल करना है. डेटा को बाइनरी फ़ॉर्म में, EXIF हेडर में स्टैंडर्ड तरीके से सेव किया जाता है. अगर आपको EXIF हेडर के लिए स्पेसिफ़िकेशन पता है, तो उन्हें खुद पार्स किया जा सकता है. अच्छी बात यह है कि किसी ने पहले ही आपके लिए Python मॉड्यूल लिख दिया है. EXIF.py ओपन सोर्स लाइब्रेरी, JPEG फ़ाइलों के हेडर पढ़ने के लिए एक बेहतरीन टूल है.
कोड
इस लेख के लिए सैंपल कोड, इस फ़ाइल में है: exif2kml.py. अगर आपको सीधे इसका इस्तेमाल करना है, तो उस मॉड्यूल के साथ-साथ EXIF.py को डाउनलोड करें और उन्हें एक ही डायरेक्ट्री में रखें. जियोटैग की गई फ़ोटो के पाथ को foo.jpg से बदलकर, python exif2kml.py foo.jpg चलाएं. इससे test.kml नाम की फ़ाइल जनरेट होगी.
Exif हेडर पार्स किए जा रहे हैं
EXIF.py, Exif हेडर को बाहर निकालने के लिए एक आसान इंटरफ़ेस उपलब्ध कराता है. सिर्फ़ process_file() फ़ंक्शन चलाएं. यह हेडर को dict ऑब्जेक्ट के तौर पर दिखाएगा.
def GetHeaders(the_file):
"""Handles getting the Exif headers and returns them as a dict.
Args:
the_file: A file object
Returns:
a dict mapping keys corresponding to the Exif headers of a file.
"""
data = EXIF.process_file(the_file, 'UNDEF', False, False, False)
return dataExif हेडर मिलने के बाद, आपको जीपीएस कोऑर्डिनेट निकालने होंगे. EXIF.py इन्हें Ratio ऑब्जेक्ट के तौर पर मानता है. ये ऑब्जेक्ट, वैल्यू के न्यूमरेटर और डिनॉमिनेटर को सेव करने के लिए होते हैं. इससे फ़्लोटिंग पॉइंट नंबर पर भरोसा करने के बजाय, सटीक अनुपात सेट अप किया जाता है. हालांकि, KML में दशमलव संख्याएं इस्तेमाल की जाती हैं, न कि अनुपात. इसलिए, हर कोऑर्डिनेट को निकाला जाता है. साथ ही, न्यूमरेटर और डिनॉमिनेटर को दशमलव डिग्री के लिए, एक फ़्लोटिंग-पॉइंट नंबर में बदला जाता है:
def DmsToDecimal(degree_num, degree_den, minute_num, minute_den,
second_num, second_den):
"""Converts the Degree/Minute/Second formatted GPS data to decimal degrees.
Args:
degree_num: The numerator of the degree object.
degree_den: The denominator of the degree object.
minute_num: The numerator of the minute object.
minute_den: The denominator of the minute object.
second_num: The numerator of the second object.
second_den: The denominator of the second object.
Returns:
A deciminal degree.
"""
degree = float(degree_num)/float(degree_den)
minute = float(minute_num)/float(minute_den)/60
second = float(second_num)/float(second_den)/3600
return degree + minute + second
def GetGps(data):
"""Parses out the GPS coordinates from the file.
Args:
data: A dict object representing the Exif headers of the photo.
Returns:
A tuple representing the latitude, longitude, and altitude of the photo.
"""
lat_dms = data['GPS GPSLatitude'].values
long_dms = data['GPS GPSLongitude'].values
latitude = DmsToDecimal(lat_dms[0].num, lat_dms[0].den,
lat_dms[1].num, lat_dms[1].den,
lat_dms[2].num, lat_dms[2].den)
longitude = DmsToDecimal(long_dms[0].num, long_dms[0].den,
long_dms[1].num, long_dms[1].den,
long_dms[2].num, long_dms[2].den)
if data['GPS GPSLatitudeRef'].printable == 'S': latitude *= -1
if data['GPS GPSLongitudeRef'].printable == 'W': longitude *= -1
altitude = None
try:
alt = data['GPS GPSAltitude'].values[0]
altitude = alt.num/alt.den
if data['GPS GPSAltitudeRef'] == 1: altitude *= -1
except KeyError:
altitude = 0
return latitude, longitude, altitude
निर्देशांक मिलने के बाद, हर फ़ोटो के लिए एक आसान PhotoOverlay बनाना आसान होता है:
def CreatePhotoOverlay(kml_doc, file_name, the_file, file_iterator): """Creates a PhotoOverlay element in the kml_doc element. Args: kml_doc: An XML document object. file_name: The name of the file. the_file: The file object. file_iterator: The file iterator, used to create the id. Returns: An XML element representing the PhotoOverlay. """ photo_id = 'photo%s' % file_iterator data = GetHeaders(the_file) coords = GetGps(data) po = kml_doc.createElement('PhotoOverlay') po.setAttribute('id', photo_id) name = kml_doc.createElement('name') name.appendChild(kml_doc.createTextNode(file_name)) description = kml_doc.createElement('description') description.appendChild(kml_doc.createCDATASection('<a href="#%s">' 'Click here to fly into ' 'photo</a>' % photo_id)) po.appendChild(name) po.appendChild(description) icon = kml_doc.createElement('icon') href = kml_doc.createElement('href') href.appendChild(kml_doc.createTextNode(file_name)) camera = kml_doc.createElement('Camera') longitude = kml_doc.createElement('longitude') latitude = kml_doc.createElement('latitude') altitude = kml_doc.createElement('altitude') tilt = kml_doc.createElement('tilt') # Determines the proportions of the image and uses them to set FOV. width = float(data['EXIF ExifImageWidth'].printable) length = float(data['EXIF ExifImageLength'].printable) lf = str(width/length * -20.0) rf = str(width/length * 20.0) longitude.appendChild(kml_doc.createTextNode(str(coords[1]))) latitude.appendChild(kml_doc.createTextNode(str(coords[0]))) altitude.appendChild(kml_doc.createTextNode('10')) tilt.appendChild(kml_doc.createTextNode('90')) camera.appendChild(longitude) camera.appendChild(latitude) camera.appendChild(altitude) camera.appendChild(tilt) icon.appendChild(href) viewvolume = kml_doc.createElement('ViewVolume') leftfov = kml_doc.createElement('leftFov') rightfov = kml_doc.createElement('rightFov') bottomfov = kml_doc.createElement('bottomFov') topfov = kml_doc.createElement('topFov') near = kml_doc.createElement('near') leftfov.appendChild(kml_doc.createTextNode(lf)) rightfov.appendChild(kml_doc.createTextNode(rf)) bottomfov.appendChild(kml_doc.createTextNode('-20')) topfov.appendChild(kml_doc.createTextNode('20')) near.appendChild(kml_doc.createTextNode('10')) viewvolume.appendChild(leftfov) viewvolume.appendChild(rightfov) viewvolume.appendChild(bottomfov) viewvolume.appendChild(topfov) viewvolume.appendChild(near) po.appendChild(camera) po.appendChild(icon) po.appendChild(viewvolume) point = kml_doc.createElement('point') coordinates = kml_doc.createElement('coordinates') coordinates.appendChild(kml_doc.createTextNode('%s,%s,%s' %(coords[1], coords[0], coords[2]))) point.appendChild(coordinates) po.appendChild(point) document = kml_doc.getElementsByTagName('Document')[0] document.appendChild(po)
यहाँ देखा जा सकता है कि हम सिर्फ़ स्टैंडर्ड W3C DOM तरीकों का इस्तेमाल कर रहे हैं, क्योंकि ये ज़्यादातर प्रोग्रामिंग भाषाओं में उपलब्ध होते हैं. यह पूरा कोड कैसे काम करता है, यह देखने के लिए यहां से कोड डाउनलोड करें.
इस सैंपल में PhotoOverlays की पूरी क्षमता का इस्तेमाल नहीं किया गया है. इसकी मदद से, ज़्यादा रिज़ॉल्यूशन वाली फ़ोटो की बारीकी से जांच की जा सकती है. हालांकि, इसमें यह दिखाया गया है कि Google Earth पर बिलबोर्ड स्टाइल में फ़ोटो कैसे लगाई जाती है. इस कोड का इस्तेमाल करके बनाई गई KML फ़ाइल का एक सैंपल यहां दिया गया है:
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<PhotoOverlay id="photo0">
<name>
1228258523134.jpg
</name>
<description>
<![CDATA[<a href="#photo0">Click here to fly into photo</a>]]> </description>
<Camera>
<longitude>
-122.3902159196034
</longitude>
<latitude>
37.78961266330473
</latitude>
<altitude>
10
</altitude>
<tilt>
90
</tilt>
</Camera>
<Icon>
<href>
1228258523134.jpg
</href>
</Icon>
<ViewVolume>
<leftFov>
-26.6666666667
</leftFov>
<rightFov>
26.6666666667
</rightFov>
<bottomFov>
-20
</bottomFov>
<topFov>
20
</topFov>
<near>
10
</near>
</ViewVolume>
<Point>
<coordinates>
-122.3902159196034,37.78961266330473,0
</coordinates>
</Point>
</PhotoOverlay>
</Document>
</kml>Google Earth में यह इस तरह दिखता है:
चेतावनी
फ़ोटो में जगह की जानकारी जोड़ने की सुविधा अभी शुरुआती दौर में है.
यहां कुछ बातें बताई गई हैं, जिनके बारे में आपको पता होना चाहिए:
- जीपीएस डिवाइस हमेशा 100% सटीक नहीं होते. खास तौर पर, कैमरे में मौजूद जीपीएस डिवाइस. इसलिए, आपको अपनी फ़ोटो की जगह की जानकारी की जांच करनी चाहिए.
- कई डिवाइस ऊंचाई को ट्रैक नहीं करते हैं. वे इसे 0 पर सेट कर देते हैं. अगर ऊंचाई आपके लिए ज़रूरी है, तो आपको उस डेटा को कैप्चर करने का कोई दूसरा तरीका ढूंढना चाहिए.
- जीपीएस पोज़िशन, कैमरे की पोज़िशन होती है. यह फ़ोटो में मौजूद व्यक्ति या ऑब्जेक्ट की पोज़िशन नहीं होती. इसलिए, इस सैंपल में Camera एलिमेंट को जीपीएस की जगह पर रखा गया है. साथ ही, असल फ़ोटो को उस जगह से दूर रखा गया है.
- Exif में यह जानकारी सेव नहीं होती कि आपका कैमरा किस दिशा में है. इसलिए, आपको
PhotoOverlaysमें बदलाव करना पड़ सकता है. अच्छी बात यह है कि Android ऑपरेटिंग सिस्टम पर बने कुछ डिवाइसों में, सीधे तौर पर डेटा कैप्चर करने की सुविधा मिलती है. जैसे, कंपास की दिशा और झुकाव. हालांकि, यह सुविधा Exif हेडर में नहीं मिलती.
इन सभी बातों के बावजूद, यह आपकी फ़ोटो को विज़ुअलाइज़ करने का एक बेहतरीन तरीका है. हमें उम्मीद है कि आने वाले समय में, फ़ोटो को ज़्यादा से ज़्यादा सटीक तरीके से जियोटैग किया जा सकेगा.
आगे क्या करें
EXIF हेडर का इस्तेमाल शुरू करने के बाद, EXIF स्पेसिफ़िकेशन के बारे में जानें. इसमें कई तरह का डेटा सेव होता है. आपको शायद इसे कैप्चर करने और ब्यौरे वाले गुब्बारे में डालने में दिलचस्पी हो. ImagePyramids का इस्तेमाल करके, बेहतर PhotoOverlays भी बनाए जा सकते हैं. PhotoOverlays के बारे में डेवलपर गाइड के लेख में, इनके इस्तेमाल के बारे में अच्छी जानकारी दी गई है.