Что нового

Получение названия места по геолокации с изображения

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Интересует возможность получить название места где было сделано изображение (iPhone к примеру, может сохранять такие данные в файл изображения).

Может есть существующие API для такой задачи? :scratch:

В iPhon'е можно видеть упорядоченность изображений по их месту съёмки, я вот хочу добиться такого же в скрипте.
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
Эта информация храница в EXIF формате...
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
alex33 [?]
Эта информация храница в EXIF формате
Я в курсе, мне нужно не с изображения вытащить информацию, а то, как её использовать.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
CreatoR [?]
Интересует возможность получить название места где было сделано изображение
Не знаю, правильно ли я вас понял.
В Autoit получить GPS Latitude и GPS Longitude из EXIF секции в фотографии можно, в ручную или посредством сторонней dll.
Может есть существующие API для такой задачи?
API есть у Google.
Источник получения GPS Latitude (25 21 32.61 S) и GPS Longitude (131 0 55.21 E)


Ответ в JSON или XML.
Lasseter Hwy Uluru NT 0872, Австралия
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Garrett [?]
В Autoit получить GPS Latitude и GPS Longitude из EXIF секции в фотографии можно, в ручную или посредством сторонней dll.
Вот также интересует решение на AutoIt, желательно без сторонней помощи.
Но это второстепенно, а вот за API от Google спасибо, буду изучать (надеюсь что там нет типичных Googl'у ограничений).
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Удалось получить вот что из файла:

Код:
Exif.GPSInfo.GPSLatitude                     Rational    3  32deg 0' 54.730" 
Exif.GPSInfo.GPSLongitude                    Rational    3  34deg 45' 6.630"

Как теперь это конвертировать в формат для API от Google?
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Вот что мне нужно было:

Код:
#CS

Links:

* http://autoit-script.ru/index.php?topic=21816.msg128138#msg128138
* http://stackoverflow.com/questions/2526304/php-extract-gps-exif-data
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
* https://www.autoitscript.com/forum/topic/179451-solved-preserve-ascpect-ratio-_gdiplus/?do=findComment&comment=1287798

#CE

#include <GDIPlus.au3>

Global Enum $iPropertyTagGpsLatitudeRef = 0x0001, $iPropertyTagGpsLatitude, $iPropertyTagGpsLongitudeRef, $iPropertyTagGpsLongitude

_GDIPlus_Startup()

$sFile = FileOpenDialog('Select image file', '', 'Images (*.jpg;*.bmp)')
If @error Then Exit

$hImage = _GDIPlus_ImageLoadFromFile($sFile)

$iLat = _ImageGetGPS($hImage, 'Latitude')
$iLon = _ImageGetGPS($hImage, 'Longitude')

_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()

$sXML = BinaryToString(InetRead(StringFormat('http://maps.google.com/maps/api/geocode/xml?latlng=%s,%s&sensor=false', $iLat, $iLon)))
$sLocation = StringRegExpReplace($sXML, '(?si).*?<formatted_address>(.*?)</formatted_address>.*', '$1')

MsgBox(64, 'Image Geolocation', $sLocation)

Func _ImageGetGPS($hImage, $iPropertyTag)
	Local $tGPS, $tProp, $iDegrees, $iMinutes, $iSeconds, $tPropRef, $iFlip
	
	$tGPS = _GDIPlus_ImageGetPropertyItem($hImage, Eval('iPropertyTagGps' & $iPropertyTag))
	$tProp = DllStructCreate("ulong dd;ulong ddn;ulong mm;ulong mmn;ulong ss;ulong ssn", $tGPS.Value)
	
	$iDegrees = $tProp.ddn > 0 ? ($tProp.dd / $tProp.ddn) : $tProp.dd
	$iMinutes = $tProp.mmn > 0 ? ($tProp.mm / $tProp.mmn) : $tProp.mm
	$iSeconds = $tProp.ssn > 0 ? ($tProp.ss / $tProp.ssn) : $tProp.ss
	
	$tGPS = _GDIPlus_ImageGetPropertyItem($hImage, Eval('iPropertyTagGps' & $iPropertyTag & 'Ref'))
	$tPropRef = DllStructCreate("char ref", $tGPS.Value)
	
	$iFlip = StringRegExp($tPropRef.ref, '(?i)^(W|S)$') ? -1 : 1
	return $iFlip * ($iDegrees + ($iMinutes / 60) + ($iSeconds / 3600))
EndFunc

; #FUNCTION# ====================================================================================================================
; Name ..........: _GDIPlus_ImageGetPropertyItem
; Description ...: Gets a specified property item (piece of metadata) from this Image object.
; Syntax ........: _GDIPlus_ImageGetPropertyItem($hImage, $iPropID)
; Parameters ....: $hImage              - A handle to an image object.
;                  $iPropID             - An integer that identifies the property item to be retrieved.
; Return values .: $tagGDIPPROPERTYITEM structure or 0 on errors
; Author ........: UEZ
; Modified ......:
; Remarks .......:
; Related .......: _GDIPlus_ImageLoadFromFile _GDIPlus_ImageLoadFromStream
; Link ..........: Property Item Descriptions -> http://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
; ===============================================================================================================================
Func _GDIPlus_ImageGetPropertyItem($hImage, $iPropID)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipGetPropertyItemSize", "handle", $hImage, "uint", $iPropID, "ulong*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aResult[0] Then Return SetError(10, $aResult[0], 0)
    Local Static $tBuffer ;why static? because otherwise it would crash when running it as x64 exe (workaround)
    $tBuffer = DllStructCreate("byte[" & $aResult[3] & "]")
    $aResult = DllCall($ghGDIPDll, "int", "GdipGetPropertyItem", "handle", $hImage, "uint", $iPropID, "ulong", $aResult[3], "struct*", $tBuffer)
    If @error Then Return SetError(@error, @extended, 0)
    If $aResult[0] Then Return SetError(11, $aResult[0], 0)
    Local Const $tagGDIPPROPERTYITEM = "uint id;ulong length;word type;ptr value"
    Local $tPropertyItem = DllStructCreate($tagGDIPPROPERTYITEM, DllStructGetPtr($tBuffer))
    If @error Then Return SetError(20, $aResult[0], 0)
    Return $tPropertyItem
EndFunc


Всем спасибо, ссылки по материалам указаны в начале кода.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
CreatoR [?]
Как теперь это конвертировать в формат для API от Google?
Код:
; 32deg 0' 54.730"
; 34deg 45' 6.630"

ConsoleWrite(_GPS_Decimal(32, 0, 54.730, "N") & @CRLF)
ConsoleWrite(_GPS_Decimal(34, 45, 6.630, "E") & @CRLF)

Func _GPS_Decimal($iDeg, $iMin, $iSec, $sRef)
	$iDeg = $iDeg + ((($iMin*60) + ($iSec)) / 3600)
	Return ($sRef=='S' Or $sRef=='W') ? Round($iDeg *- 1, 6) : Round($iDeg, 6)
EndFunc



Добавлено:
Сообщение автоматически объединено:

CreatoR
Код:
$ghGDIPDll ; imho замените на $__g_hGDIPDll

Код:
;~ Variable must be of type "Object".:
;~ $tProp = DllStructCreate("ulong dd;ulong ddn;ulong mm;ulong mmn;ulong ss;ulong ssn", $tGPS.Value)
;~ $tProp = DllStructCreate("ulong dd;ulong ddn;ulong mm;ulong mmn;ulong ss;ulong ssn", $tGPS^ ERROR
;~ Возникает когда в фото нету данных GPS.

;~ ...
$tGPS = _GDIPlus_ImageGetPropertyItem($hImage, Eval('iPropertyTagGps' & $iPropertyTag))
If Not IsDllStruct($tGPS) Then
	Return 0
EndIf
;~ ...

P.S. IMHO функцию в "Полезняшки" однозначно.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Garrett [?]
В этом и проблема пользовательских UDF. Не думают люди о совместимости.
Тот кто написал функцию как раз таки использовал $__g_hGDIPDll, это я уже для себя изменил :laugh:.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
А вот интересно, то что делает Google Maps API, можно делать локально?
Я имею в виду получение данных по координатам GPS, может есть где то в сети некая готовая база данных, которую можно сохранить локально и использовать без обращения в сеть каждый раз?
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
CreatoR [?]
может есть где то в сети некая готовая база данных
Наверняка есть.


Добавлено:
Сообщение автоматически объединено:

Там есть .dbf файлы.


Добавлено:
Сообщение автоматически объединено:

Можно ещё здесь посмотреть.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Garrett
Я пришёл к выводу что это не рентабельно, тем более что базы не полные и постоянно обновляются.
Может всё таки в самом изображений где то хранится название геолокации? :scratch:
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
CreatoR [?]
Я пришёл к выводу что это не рентабельно, тем более что базы не полные и постоянно обновляются.
Адская работа, согласен. :smile:
Как вариант, можно наполнять локальную базу (ЛБД) при каждом запросе к Google.
1. Запрос к локальной базе данных.
2. Если нет информации:
2.1 Запрос к Google и запись в ЛБД.
2.2 Иначе:
2.3 Вытаскиваем информацию из ЛБД.

При частом использовании программы, ЛБД наполнится сравнительно быстро.

Может всё таки в самом изображений где то хранится название геолокации?
IMHO все зависит от самого устройства на котором была сделана фотография. В большинстве случаев нет.
Однако никто не мешает добавить название в EXIF.
 
Верх