Ocak 2009
Hedef
Bu eğitimde, KML PhotoOverlays
oluşturmak için coğrafi etiketli fotoğrafları nasıl kullanacağınız açıklanmaktadır. Örnek kod Python'da yazılmış olsa da diğer programlama dillerinde de benzer birçok kitaplık vardır. Bu nedenle, bu kodu başka bir dile çevirmek sorun olmaz. Bu makaledeki kod, açık kaynaklı bir Python kitaplığı olan EXIF.py'yi kullanır.
Giriş
Dijital kameralar oldukça etkileyici cihazlardır. Birçok kullanıcı farkında olmasa da fotoğraf ve video çekmenin ötesinde işlemler yapıyor. Ayrıca bu videoları ve fotoğrafları kamera ve ayarlarıyla ilgili meta verilerle etiketler. Son birkaç yıldır kullanıcılar, bu bilgilere coğrafi veriler eklemenin yollarını buldu. Bu veriler, bazı Ricoh ve Nikon kameralar gibi kamera üreticileri tarafından yerleştirilebildiği gibi GPS kaydediciler ve EyeFi Explore gibi cihazlar aracılığıyla da eklenebiliyor. iPhone gibi kameralı telefonlar ve Android işletim sistemini kullanan telefonlar (ör. T-Mobile'ın G1) bu verileri otomatik olarak yerleştirir. Panoramio, Picasa Web Albümleri ve Flickr gibi bazı fotoğraf yükleme siteleri, GPS verilerini otomatik olarak ayrıştırır ve fotoğrafa coğrafi etiket eklemek için kullanır. Bu verileri daha sonra feed'lerde tekrar kullanabilirsiniz. Ama bunun neresi eğlenceli? Bu makalede, bu verilere kendiniz nasıl ulaşabileceğiniz açıklanmaktadır.
EXIF üstbilgileri
Verileri bir resim dosyasına yerleştirmenin en yaygın yolu Değiştirilebilir Resim Dosyası Biçimi (EXIF) kullanmaktır. Veriler, standart bir şekilde EXIF başlıklarında ikili biçimde depolanır. EXIF üstbilgilerinin özelliklerini biliyorsanız bunları kendiniz ayrıştırabilirsiniz. Neyse ki bir kullanıcı bu zorlu işi sizin için yapmış ve bir Python modülü yazmış. EXIF.py açık kaynak kitaplığı, JPEG dosyalarının başlıklarını okumak için harika bir araçtır.
The Code
Bu makaledeki örnek kod şu dosyada yer alır: exif2kml.py. Doğrudan kullanmaya başlamak istiyorsanız bu modülün yanı sıra EXIF.py dosyasını da indirip aynı dizine yerleştirin. python exif2kml.py foo.jpg
komutunu çalıştırın ve foo.jpg yerine coğrafi etiketli bir fotoğrafın yolunu girin. test.kml
adlı bir dosya oluşturulur.
Exif üstbilgilerini ayrıştırma
EXIF.py, Exif başlıklarını çekmek için kolay bir arayüz sağlar. process_file()
işlevini çalıştırmanız yeterlidir. Bu işlev, başlıkları dict
nesnesi olarak döndürür.
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 data
Exif üstbilgilerini aldıktan sonra GPS koordinatlarını çıkarmanız gerekir. EXIF.py, bunları Ratio
nesneleri olarak ele alır. Bu nesneler, değerlerin payını ve paydasını depolamak için kullanılır. Bu, kayan nokta sayısı kullanmak yerine kesin bir oran belirler. Ancak KML, oran değil ondalık sayılar bekler. Bu nedenle, her bir koordinatı ayıklayıp pay ve paydayı ondalık derece için tek bir kayan noktalı sayıya dönüştürürsünüz:
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
Koordinatları aldıktan sonra her fotoğraf için basit bir PhotoOverlay
oluşturmak kolaydır:
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)
Çoğu programlama dilinde kullanılabilen standart W3C DOM yöntemlerini kullandığımızı görebilirsiniz. Her şeyin nasıl bir araya geldiğini görmek için kodu buradan indirin.
Bu örnek, yüksek çözünürlüklü fotoğrafları ayrıntılı bir şekilde incelemenize olanak tanıyan PhotoOverlays
'nın tüm gücünden yararlanmıyor. Ancak, Google Earth'te billboard tarzında fotoğraf asma işleminin nasıl yapılacağını gösterir. Bu kod kullanılarak oluşturulan bir KML dosyası örneğini aşağıda bulabilirsiniz:
<?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'te ise şu şekilde görünür:

Dikkat Edilecek Noktalar
Fotoğraflara coğrafi etiket ekleme özelliği henüz geliştirme aşamasındadır.
Dikkat etmeniz gereken birkaç nokta:
- GPS cihazlar, özellikle kameralarda bulunanlar, her zaman% 100 doğru olmayabilir. Bu nedenle, fotoğraflarınızın konumlarını kontrol etmeniz gerekir.
- Birçok cihaz, yüksekliği takip etmez ve bunun yerine 0 olarak ayarlar. Yükseklik sizin için önemliyse bu verileri yakalamak için başka bir yöntem bulmanız gerekir.
- GPS konumu, fotoğrafın öznesinin değil, kameranın konumudur. Bu nedenle, bu örnekte Kamera öğesi GPS konumuna, gerçek fotoğraf ise bu konumdan uzağa yerleştirilir.
- Exif, kameranızın yönüyle ilgili bilgileri yakalamaz. Bu nedenle,
PhotoOverlays
ayarınızı buna göre yapmanız gerekebilir. İyi haber ise Android işletim sistemi üzerine kurulu telefonlar gibi bazı cihazların, pusula yönü ve eğim gibi verileri doğrudan yakalamanıza izin vermesidir. Bu veriler yalnızca Exif başlıklarında yer almaz.
Tüm bunlara rağmen, bu özellik fotoğraflarınızı görselleştirmenin güçlü bir yoludur. Umarız yakın gelecekte fotoğrafların coğrafi etiketlenmesi daha doğru ve yaygın bir şekilde yapılır.
Sonraki adımlar
EXIF üstbilgilerini kullanmaya başladığınıza göre EXIF spesifikasyonunu inceleyebilirsiniz. Burada depolanan başka birçok veri vardır ve bunları yakalayıp açıklama balonuna yerleştirmek isteyebilirsiniz. Ayrıca, ImagePyramids
kullanarak daha zengin PhotoOverlays
oluşturmayı da düşünebilirsiniz. PhotoOverlays
ile ilgili Geliştirici Kılavuzu makalesinde bu reklamların kullanımıyla ilgili iyi bir genel bakış sunulmaktadır.