জানুয়ারী 2009
উদ্দেশ্য
এই টিউটোরিয়ালটি আপনাকে শেখায় কিভাবে কেএমএল PhotoOverlays
তৈরি করতে জিওট্যাগ করা ফটো ব্যবহার করতে হয়। যদিও নমুনা কোডটি পাইথনে লেখা হয়, অনেক অনুরূপ লাইব্রেরি অন্যান্য প্রোগ্রামিং ভাষায় বিদ্যমান, তাই এই কোডটিকে অন্য ভাষায় অনুবাদ করতে সমস্যা হওয়া উচিত নয়। এই নিবন্ধের কোডটি একটি ওপেন-সোর্স পাইথন লাইব্রেরির উপর নির্ভর করে, EXIF.py।
ভূমিকা
ডিজিটাল ক্যামেরা বেশ আশ্চর্যজনক জিনিস। অনেক ব্যবহারকারী এটা বুঝতে পারে না, কিন্তু তারা শুধু ছবি এবং ভিডিও তোলার চেয়ে বেশি কিছু করে। তারা ক্যামেরা এবং এর সেটিংস সম্পর্কে মেটাডেটা সহ সেই ভিডিও এবং ফটোগুলিকে ট্যাগ করে। গত কয়েক বছরে, লোকেরা সেই তথ্যে ভৌগলিক ডেটা যোগ করার উপায় খুঁজে পেয়েছে, হয় ক্যামেরা নির্মাতাদের দ্বারা এমবেড করা, যেমন কিছু Ricoh এবং Nikon ক্যামেরা, বা GPS লগার এবং EyeFi এক্সপ্লোরের মতো ডিভাইসগুলির মাধ্যমে। আইফোনের মতো ক্যামেরা ফোন এবং অ্যান্ড্রয়েড অপারেটিং সিস্টেম ব্যবহার করা ফোন, যেমন T-Mobile-এর G1 , সেই ডেটা স্বয়ংক্রিয়ভাবে এম্বেড করে। কিছু ফটো আপলোড সাইট, যেমন Panoramio , Picasa ওয়েব অ্যালবাম , এবং Flickr , GPS ডেটা স্বয়ংক্রিয়ভাবে বিশ্লেষণ করবে এবং একটি ফটো জিওট্যাগ করতে এটি ব্যবহার করবে৷ তারপরে আপনি সেই ডেটা ফিডগুলিতে ফিরে পেতে পারেন। কিন্তু তাতে মজা কোথায়? এই নিবন্ধটি অন্বেষণ করে যে কীভাবে সেই ডেটা নিজে পেতে হয়।
Exif হেডার
একটি ইমেজ ফাইলে ডেটা এম্বেড করার সবচেয়ে সাধারণ উপায় হল এক্সচেঞ্জেবল ইমেজ ফাইল ফরম্যাট বা EXIF ব্যবহার করা। ডেটা বাইনারি আকারে EXIF শিরোনামে একটি আদর্শ উপায়ে সংরক্ষণ করা হয়। আপনি যদি EXIF শিরোনামগুলির জন্য স্পেসিফিকেশন জানেন তবে আপনি সেগুলি নিজেই বিশ্লেষণ করতে পারেন৷ ভাগ্যক্রমে, কেউ ইতিমধ্যে কঠোর পরিশ্রম করেছে এবং আপনার জন্য একটি পাইথন মডিউল লিখেছে। EXIF.py ওপেন সোর্স লাইব্রেরি একটি JPEG ফাইলের শিরোনাম পড়ার জন্য একটি দুর্দান্ত সরঞ্জাম।
কোড
এই নিবন্ধটির নমুনা কোড এই ফাইলটিতে রয়েছে: exif2kml.py । আপনি যদি সরাসরি এটি ব্যবহার করতে এড়িয়ে যেতে চান, সেই মডিউলটি ডাউনলোড করুন, সেইসাথে EXIF.py , এবং সেগুলিকে একই ডিরেক্টরিতে রাখুন৷ python exif2kml.py foo.jpg
চালান 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 data
একবার আপনার এক্সিফ হেডার হয়ে গেলে, আপনাকে জিপিএস স্থানাঙ্কগুলি বের করতে হবে। EXIF.py এগুলিকে Ratio
বস্তু, লব এবং মানগুলির হর সংরক্ষণের জন্য বস্তু হিসাবে বিবেচনা করে। এটি একটি ফ্লোটিং পয়েন্ট সংখ্যার উপর নির্ভর না করে একটি সুনির্দিষ্ট অনুপাত সেট আপ করে। কিন্তু, কেএমএল দশমিক সংখ্যা আশা করে, অনুপাত নয়। সুতরাং আপনি প্রতিটি স্থানাঙ্ক বের করুন, এবং দশমিক ডিগ্রীর জন্য লব এবং হরকে একটি একক ভাসমান-বিন্দু সংখ্যায় রূপান্তর করুন:
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
এর সম্পূর্ণ শক্তির সুবিধা নেয় না, যা আপনাকে উচ্চ রেজোলিউশনের ফটোগুলির গভীর অনুসন্ধান তৈরি করতে দেয়৷ তবে, এটি প্রদর্শন করে যে কীভাবে একটি বিলবোর্ড স্টাইলে গুগল আর্থের উপর একটি ফটো ঝুলানো যায়। এই কোডটি ব্যবহার করে তৈরি করা একটি 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>
এবং গুগল আর্থে এটি দেখতে কেমন তা এখানে:

সতর্কতা
জিওট্যাগিং ফটো এখনও তার শৈশবকালে।
এখানে বেশ কয়েকটি বিষয় সম্পর্কে সচেতন হতে হবে:
- জিপিএস ডিভাইস সবসময় 100% নির্ভুল হয় না, বিশেষ করে যেগুলি ক্যামেরায় আসে, তাই আপনার ফটোগুলির অবস্থান পরীক্ষা করা উচিত।
- অনেক ডিভাইস উচ্চতা ট্র্যাক করে না, পরিবর্তে এটি 0 তে সেট করে। যদি উচ্চতা আপনার কাছে গুরুত্বপূর্ণ হয়, তাহলে সেই ডেটা ক্যাপচার করার জন্য আপনার অন্য উপায় খুঁজে বের করা উচিত।
- জিপিএস অবস্থান হল ক্যামেরার অবস্থান, ছবির বিষয় নয়। এই কারণেই এই নমুনাটি ক্যামেরা উপাদানটিকে GPS অবস্থানে অবস্থান করে এবং প্রকৃত ফটোটিকে সেই অবস্থান থেকে দূরে রাখে।
- Exif আপনার ক্যামেরা যে দিকে নির্দেশ করছে সে সম্পর্কে তথ্য ক্যাপচার করে না, তাই এর কারণে আপনাকে আপনার
PhotoOverlays
সামঞ্জস্য করতে হতে পারে। ভাল খবর হল যে কিছু ডিভাইস, যেমন অ্যান্ড্রয়েড অপারেটিং সিস্টেমে তৈরি ফোন, আপনাকে কম্পাসের দিকনির্দেশ এবং সরাসরি কাত করার মতো ডেটা ক্যাপচার করতে দেয়, শুধু Exif হেডারে নয়।
যা বলা হচ্ছে, এটি এখনও আপনার ফটোগুলি কল্পনা করার একটি শক্তিশালী উপায়। আশা করি, আমরা অদূর ভবিষ্যতে ফটোগুলির আরও বেশি সঠিক জিওট্যাগিং দেখতে পাব।
এখান থেকে কোথায় যেতে হবে
এখন আপনি EXIF শিরোনাম ব্যবহার করা শুরু করেছেন, আপনি EXIF spec অন্বেষণ করতে পারেন। সেখানে প্রচুর পরিমাণে অন্যান্য ডেটা সংরক্ষিত আছে, এবং আপনি এটি ক্যাপচার করতে আগ্রহী হতে পারেন, এটি একটি বর্ণনা বেলুনে রেখে। আপনি ImagePyramids
ব্যবহার করে আরও সমৃদ্ধ PhotoOverlays
তৈরি করার কথাও বিবেচনা করতে পারেন। PhotoOverlays
বিকাশকারীর গাইড নিবন্ধে সেগুলি ব্যবহার করার একটি ভাল ওভারভিউ রয়েছে৷