Как определить координаты пикселя на картинке

Обновлено: 04.07.2024

Есть ли другие алгоритмы пересчета? как вообще реализуется пересчет без использования конвертора яндекс-карт?

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

да, но по ссылке показан пример преобразования геокоординат в тайлы, а меня интересует из пиксельных в географические.

map.events.add('click', function (e)

var zoom = map.getZoom();

чтоб при клике на карту получить глобальные пикселы карты, а потом через ajax их передать на сервер, где их обработать и как результат получить геокоординаты, без использования converter яндекс-карт.

Вот тут модуль меркатора, который работает и туда и обратно

благодарю. буду разбираться. :-)

я извиняюсь, вот дочитала до места где

return value - Math.floor((value - min) / (max - min)) * (max - min);

вопрос, вот например

здесь х - это координата глобального пиксела?

т.е. то что я получаю из

map.events.add('click', function (e)

Именно она. Пиксельные координаты везде одинаковые

что-то у меня не выходит, что нужно

из модуля, что Вы мне скинули, я списала:

public static function cycleRestrict($value,$min,$max)

return floor((($value - $min)/($max - $min))*($max - $min));

public static function pixelToGeo($pixelX,$pixelY)

$subradius = 1 / $radius;

$d2 = $e2 / 2 + 5 * $e4 / 24 + $e6 / 12 + 13 * $e8 / 360;

$d4 = 7 * $e4 / 48 + 29 * $e6 / 240 + 811 * $e8 / 11520;

$d6 = 7 * $e6 / 120 + 81 * $e8 / 1120;

$d8 = 4279 * $e8 / 161280;

$c_pi180 = M_PI / 180;

$c_180pi = 180 / M_PI;

$geoX = self::cycleRestrict($pixelX * $subradius, -M_PI, M_PI) * $c_180pi;

$xphi = M_PI * 0.5 - 2 * atan(1 / exp($pixelY * $subradius));

$geoY = $xphi + $d2 * sin(2 * $xphi) + $d4 * sin(4 * $xphi) + $d6 * sin(6 * $xphi) + $d8 * sin(8 * $xphi);

$geoY = $geoY * $c_180pi;

return array('x' => $geoX, 'y' => $geoY);

map.events.add('click', function (e)

Координаты щелчка: ' + coords.join(', ') + '

Глобальные пикселы '+pixels.join(', ')+'

Ответ с сервера
'+res+'

Координаты щелчка: 47.918725916901664, 33.42612788639918 // то, что должны получить

Глобальные пикселы 155412.16352403397, 91420.96006116038 // входные параметры
Ответ с сервера
171,88733853925 0,82675418263993 // что отдала функция преорбразования с сервера

а нужно получить выведенные координаты щелчка, где я прошляпила ?
и еще вопрос, а почему нигде в формулах не учитывается величина зума (как мне показалось из документации яндекса, то тоже должно зависеть)?

Потому что результатом работы функции являются пиксельные координаты на "нулевом зуме", надо доможнить на 2<

Но циферки в любом случае как-то не срастаются :(

$pixelX = ($pixelX * 2) << $zoom;

$pixelY = ($pixelY * 2) << $zoom;

так? так а в чем принцип смещения на значение зума?

битовый сдвиг по сути равняется возведению в степень. Вот только так делаете вы - делать нельзя.

Битовому сдвигу подведждены только целые числа, и pixelX*2 будет в начале округлен, потом возведен степень.

Вот только возводить надо исключительно "двойку" и лучше в скобочках.

И чет я сам совсем запутался в этих формулах - раньше в одном месте были, теперь уже в двух.

globalPixelXToGeo = function (x, zoom)

return cycleRestrict(Math.PI * x / Math.pow(2, zoom + 7) - Math.PI, -Math.PI, Math.PI) * (180 / Math.PI);

>;

+ yToLatitude(halfEquator - vector[1] / pixelsPerMeter) ;

Вот что у меня было в коде, из вышеизложенного кода

public static function fromGlobalsPixels($vectorX, $vectorY, $zoom)

$vectorX = $vectorX * $coef;

$vectorY = $vectorY * $coef;

$equator = 2 * M_PI * $radius;

$subequator = 1 / $equator;

$halfEquator = $equator / 2;

$c_180pi = 180 / M_PI;

$pixelsPerMeter = 256 * $subequator;

if ($zoom != $currentZoom)

$pixelsPerMeter = pow(2, $zoom + 8) * $subequator;

$vectorX = self::cycleRestrict(M_PI * $vectorX / pow(2, $zoom + 7) - M_PI, -M_PI, M_PI) * $c_180pi;

$vectorY = self::yToLatitude($halfEquator - $vectorY / $pixelsPerMeter);

return array('x' => $vectorX, 'y' => $vectorY);

public static function xToLongtitude($vectorX, $zoom)

$c_180pi = 180 / M_PI;

return self::cycleRestrict(M_PI * $vectorX / pow(2, $zoom + 7) - M_PI, -M_PI, M_PI) * $c_180pi;

public static function yToLatitude($vectorY)

$subradius = 1 / $radius;

$d2 = $e2 / 2 + 5 * $e4 / 24 + $e6 / 12 + 13 * $e8 / 360;

$d4 = 7 * $e4 / 48 + 29 * $e6 / 240 + 811 * $e8 / 11520;

$d6 = 7 * $e6 / 120 + 81 * $e8 / 1120;

$d8 = 4279 * $e8 / 161280;

$c_180pi = 180 / M_PI;

$xphi = M_PI * 0.5 - 2 * atan(1 / exp($vectorY * $subradius));

$geoY = $xphi + $d2 * sin(2 * $xphi) + $d4 * sin(4 * $xphi) + $d6 * sin(6 * $xphi) + $d8 * sin(8 * $xphi);

$geoY = $geoY * $c_180pi;

Координаты щелчка: 47.90303007897467, 33.38492915593044 // что должны получить

Глобальные пикселы 155382.16352403397, 91437.96006117242 // входные данные

Ответ с сервера

Геокоординаты: 0 85,08405905011

опять неудача.
Хотя вот без домножения на $coef, оч близко вышла координата Y.

Не, разницы между 2.0.35,26 и даже 2.1 в этом месте нету.

Но вижу ошибку- $coef = 2 >> $zoom - оно просто 0 даст. Надо pow(2,-zoom), или 2<

$vectorY = $vectorY/$coef;
но эффекта не дало все равно((

Координаты щелчка: 47.91041695223366, 33.40690181218043

Глобальные пикселы 155398.16352403397, 91429.96006116032
Геокоординаты: 0 85,078802204116

Я теперь ничего не понимаю. То поделить, то умножить. Хочу понять, какая логика вообще заложена при переведении координат с учетом зума?

Какую роль несет переменная $pixelsPerMeter?

зачем вообще переводить глобальные пикселы, которые я вытащила, если отсюда, из того что я нашла ниже в модуле, оно уже "отформатировала" нужные пикселы?

$vectorY = self::yToLatitude($halfEquator - $vectorY / $pixelsPerMeter); // значение выдает тютилька в тютильку, если не делать никакого домножения/деления
а вот с этой частью
$vectorY = self::yToLatitude($halfEquator - $vectorY / $pixelsPerMeter); . огромное расхождение, координаты не совпадают

Ошибка в cycleRestrict, и $coef не нужен (зум тут и так есть, в том числе в $pixelsPerMeter)

public static function cycleRestrict($value, $min, $max)

return $value - floor(($value - $min) / ($max - $min)) * ($max - $min);

>

public static function fromGlobalsPixels($vectorX, $vectorY, $zoom)

$coef = 1; //2 >> $zoom;

$vectorX = $vectorX * $coef;

$vectorY = $vectorY * $coef;

$radius = 6378137;

$equator = 2 * M_PI * $radius;

$subequator = 1 / $equator;

$halfEquator = $equator / 2;

$c_180pi = 180 / M_PI;

$pixelsPerMeter = pow(2, $zoom + 8) * $subequator;

$vectorX = self::cycleRestrict(M_PI * $vectorX / pow(2, $zoom + 7) - M_PI, -M_PI, M_PI) * $c_180pi;

$vectorY = self::yToLatitude($halfEquator - $vectorY / $pixelsPerMeter);

return array('x' => $vectorX, 'y' => $vectorY);

>

Идея записывать вместе с каждой фотографией координаты точки, в которой они сделаны, возникла еще на заре цифровой фотографии и была почти сразу реализована. Сегодня эта идея пришла в массы и обросла множеством сервисов. С самого начала возникла и сегодня продолжается реализация идеи на аппаратном уровне, когда GPS приемник прямо связывается с камерой, либо он в нее встроен, либо подсоединен к ней через последовательный порт, либо установлен на камеру и получает сигнал о том, что сделан снимок, от синхроконтакта вспышки. Sony выпустила также устройство GPS-CS1, которое записывает просто координаты каждые 15 с, а потом они синхронизуются по времени со сделанными снимками, и информация о координатах записывается в файле. Учитывая, что сегодня и GPS приемники, и камеры стали весьма распространенными и в повседневной жизни, возможно, вам и не придется покупать дополнительное устройство, можно воспользоваться уже имеющимся у вас GPS приемником и камерой, остается только привязать данные о координатах к конкретным снимкам. Раньше было существенное ограничение, связанное с тем, что память GPS навигатора переполнялась, и приходилось каждый день скачивать информацию в компьютер. Если вы снимали редко, а GPS использовался в навигации, то вполне вероятно, что, приехав из похода, вы сможете извлечь информацию только о последнем дне. Сейчас, когда у GPS навигаторов появилась возможность записывать пройденные пути на карты памяти, вопрос ее нехватки практически полностью снят. В Интернете можно найти несколько десятков программ, предназначенных для привязки фотографий к координатам. Более менее полный список можно найти здесь и здесь. Среди них есть и коммерческие, но большинство бесплатные и даже с открытыми исходными кодами. Я попытался попробовать многие их них, однако если по каким-то причинам программа сразу не начинала работать корректно, то я не пытался разобраться, а сразу переходил к следующей. Поэтому весьма вероятно, что среди тех программ, которые я отбраковал, есть и достойные, которые на другой конфигурации оборудования начнут работать сразу и без проблем. Коммерческие программы я тоже не рассматривал, поскольку их демонстрационные версии вносят умышленную ошибку около километра, и мне показалось неразумным тратить на них время при наличии большого количества открытых программ.

Кроме того, число рассматриваемых программ сократилось, поскольку у меня были достаточно специфические дополнительные требования. А именно: для записи координат использовался навигатор Etrex Venture Cx, который сохраняет данные о координатах в формате GPX (GPS Exchange Format). Формат стандартный, но выясняется, что фирма Garmin и некоторые создатели программ этот стандарт понимают по-разному. К счастью, есть универсальные программы, преобразующие один формат в другой. И среди них я бы выделил GPSBabel. В частности, в этой программе можно попросить преобразовать формат GPX, взятый из навигатора Garmin, в тот же самый формат, но результат этого преобразования будут понимать уже все программы.

Второе требование состояло в том, что мне хотелось сразу привязать фотографии в формате RAW, чтобы все полученные из исходных фотографии были уже с помеченными координатами, и не надо было бы снова определять координаты по времени, когда сделан снимок. Потому что с временем, как оказалось, существует довольно много проблем. И если их еще умножить тем, что преобразованные файлы сделаны и обработаны в разное время, и исходная информация времен снимка может быть потеряна или через некоторое время вы не сможете вспомнить, в каком часовом поясе вы снимали. Многие из рассмотренных мной программ имеют довольно изощренные настройки для коррекции возможных проблем с установкой времен. Тем не менее, лучше сразу настроить навигатор и камеру таким образом, чтобы этих проблем не возникало. У моего навигатора есть возможность выбрать способ записи трека — автоматический или через заданный интервал времени. В автоматическом режиме, если вы быстро перемещаетесь, то точек пишется много, если же стоите на месте, то они вообще не пишутся. Это позволяет получить запись пути одинаково качественно, передвигаетесь ли вы пешком, или едете на машине. Однако если вы долго снимаете с одной точки, то может создаться ситуация, когда в момент съемки GPS навигатор не записал координаты, поскольку они не отличались от записанных полчаса назад. Во многих программах можно задать интервал времени, в котором координаты считаются совпадающими со сделанным снимком. Однако отсутствие информации может означать не только то, что вы не перемещались, но и то, что сигнал от спутника был потерян. В этом случае, если интервал достаточно большой, то снимку могут быть приписаны координаты, существенно отличающиеся от истинных. Поэтому я рекомендую установить запись по времени с интервалом в 10 с. Если вы снимаете не из окна автобуса, то точность будет более чем достаточна.

Итак, если у нас камера и навигатор установлены по единому времени, то в дальнейшем можно игнорировать настройки Часовой пояс. Программы привязки фотографии к координатам

GPicSync

Для начальной пакетной обработки снятых фотографий я выбрал программу GPicSync.

GPicSinc

Спартанский графический интерфейс, работа только с папками, просмотр только JPEG, но свою задачу она выполняет и достаточно быстро. Отмечу, что есть довольно много программ, работающих из командной строки, которые могут поспорить с данной по аскетизму, но я не люблю работать с клавиатурой :-) Программа использует EXIFTool и GPSbabel. Распространяется по лицензии GPL. Есть версии для Windows и Linux. Поддерживается русский язык.

Работает она сразу с папками, позволяет пакетно преобразовывать сразу много фотографий, работает с RAW, понимает файлы GPX от Garmin, записывает координаты в EXIF, позволяет добавлять автоматически в ключевые слова IPTC ближайшие географические названия, которые она берет из баз данных в Интернете. Кроме того, что она записывает информацию о координатах в файлы фотографий, она также создает файл в формате KML или KMZ.

KML (Keyhole Markup Language — язык разметки Keyhole) — язык разметки на основе XML, служащий для представления трехмерных геопространственных данных в программе Google Earth, которая носила название «Keyhole» до её приобретения компанией Google. KMZ являются результатом сжатия KML-файлов ZIP-способом. Подробнее см здесь.

Программа Google Earth распространяется бесплатно здесь.

Google Earth

MapSource

Geotag

Для работы с отдельными фотографиями может оказаться хорошим выбором программа Geotag.

geotag

Эта программа написана на Java и, как следствие, одинаково легко запускается без переустановки и под Windows, и под Linux. Кроме того, она распространяется по лицензии GNU General Public License. Программа может все: работать с RAW файлами; просматривать их; записывать координаты в EXIF; просматривать положение фотографий на спутниковых снимках через программу Google Earth; добавлять географические названия в ключевые слова, пользуясь информацией с сайта GeoNames. Чтобы добиться такой универсальности, программа использует внешние модули сторонних разработчиков, которые надо устанавливать отдельно: ExifTool by Phil Harvey, GPSBabel, dcraw by Dave Coffin.

Google

Программа очень часто обновляется, так что есть надежда, что она будет совершенствоваться :-)

COPIKS PhotoMapper

Если работать только с файлами в формате JPEG и только под Windows, то неплохим выбором будет программа COPIKS PhotoMapper.

PhotoMapper

Она же весьма эффективно справляется с задачей упаковки ранее привязанных к координатам фотографий в формат KMZ. Можно посмотреть, как это выглядит, скачав файл в 500 КБ.

Locr GPS Photo

Для последующей обработки и размещения фотографий в интернете может быть полезной программа Locr GPS Photo.

locr

Удобна она и тем, что позволяет накладывать фотографии на космические снимки и карты, предоставленные разными компаниями. Можно выбирать между Google, Microsoft и YAHOO.

locr

Привязывать фотографии с ее помощью я так и не научился, поскольку не нашел способа преобразовать GPX в приемлемый для нее формат NMEA. Поэтому для меня ее основное предназначение размещать фотографии в интернете. Это не единственная служба которая предоставляет подобную услугу, можно размещать фотографии в интернете и на сайте Panoramio.

Panorado Flyer

Удобным дополнением оказалась программа Panorado Flyer, которая позволяет редактировать координаты вручную, находить точку съемки в программе Google Earth по данным, записанным в EXIF, а также проводить обратную операцию — записывать координаты найденной на космическом снимке точки съемки в EXIF.

Panorado Flyer

За последний год идея получила бурную поддержку в массах, и скоро любую точку земной поверхности можно будет увидеть не только из космоса, но и с уровня земли. Включив в Google Earth слой «География в интернете/Panoramio», вы увидите, что земля буквально усыпана пометками точек съемки, щелкнув по которым, можно увидеть фотографию.

Python - используйте OpenCV, чтобы получить координаты точки пикселя, в которой мышь щелкает по изображению.

Введение в OpenCV

OpenCV был создан Гэри Брадски в корпорации Intel в 1999 году, а первая версия была выпущена в 2000 году. Вадим Писалевский присоединяется к Гэри Бласки, чтобы управлять командой Intel Russian Software OpenCV. В 2005 году OpenCV использовался в Стэнли, этот автомобиль выиграл главный конкурс Агентства перспективных исследовательских проектов Министерства обороны США в 2005 году. Позже при поддержке Willow Garage проект продолжил активно развиваться под руководством Гэри Брадского и Вадима Писаревского. В настоящее время OpenCV поддерживает множество алгоритмов, связанных с компьютерным зрением и машинным обучением, и расширяется с каждым днем. В настоящее время OpenCV поддерживает множество языков программирования, таких как c ++, Python, Java и т. Д., И может использоваться на разных платформах, включая Windows, Linux, OS X, Android, iOS и т. Д. Кроме того, интерфейсы на основе CUDA и OpenCL также активно разрабатываются для высокоскоростных операций с графическим процессором. OpenCV-Python - это Python API OpenCV. Он сочетает в себе лучшие возможности OpenCV c ++ API и языка Python.

Реальный столбец

Функция получения пикселей в основном основана на встроенной в OpenCV функции cv2.setMouseCallback (), то есть обратном вызове события мыши. Давайте посмотрим, как использовать эту функцию в официальной документации:

Среди них очень простая функция draw_circle, которая заключается в рисовании круга в месте двойного щелчка.
Код состоит всего из двух предложений,Если обнаружено событие мыши, нарисуйте круг размером 100 в координатах двойного щелчка мыши., Поскольку OpenCV считывает, что метод изображения относится к типу BGR, цвет здесь синий
Затем ниже создается окно изображения размером 512 * 512, вызывается функция CALL, отображается изображение и закрывается при обнаружении ESC.
Кстати, вот "&0xFF"Это для 64-битной системы, если 32-битную здесь нужно удалить, 27 - это код ASCII, представляющий ESC
Результаты следующие:



Согласно этой официальной программе, мы хотим получить значение координаты xy очень просто, достаточно взглянуть на код:


Эффект такой:

Нажмите ESC для выхода

Не могу найти информацию - существует ли линейная зависимость между пиксельными координатами? Если да, то какая?

Есть две точки с известными пиксельными координатами в масштабе 18 возможно ли вычислить между ними расстояние используя операции сложения, умножения и извлечения корня?

Нашёл решение. Если расстояние в метрах умножить на 1,53 - получим расстояние в пикселах в масштабе 17. Цифра получена эмпирически. Буду благодарен, если кто-то подскажет теоретическое значение коэффициента.

Полагаю, что этот коэфф. зависит от широты места, поэтому ваше значение актуально для того мста, где вы экспериментировали

Вообще изображение в тайле является снимком местности, которое получено со спутника с фиксированой разрешающей способностью. Соответственно размер точки не зависит от части земного шара. Кроме того линейка масштаба на карте не зависит от широты и долготы.

Как раз таки геокоординаты не имеют линейного преобразования в метры.

Максим, сделайте эксперимент - откройте Яндекс карты, заметьте значение масштаба на линейке внизу и походите вдоль меридиана. Заметьте изменение цифр масштаба.
Что касается тайлов - Яндекс публикует не сырые снимки с фикс. разреш. способностью, а обработанные, приведенные к единому виду и масштабу.
Что касается линейности - в исходном посте вы упоминали корень, что теоретически дает вам возможность уйти из линейных преобразований

Да действительно, при одном и том же масштабе отображения в районе северного ледовитого океана масштаб на линейке изменяется скачкообразно в 2 раза, при этом какого-либо стыка на картинках не видно. Зато по территории России проблем я не заметил. Расстояние между москвой и екб - вполне поддаётся пиксельной оценке.

И москва - владивосток в пикселях тоже вычисляется нормально.

Во-первых, вам какое расстояние надо - кратчайшее или "по прямой"? Это разные вещи.

Если вас устраивает "по прямой", то в пиксельных координатах более-менее похожее на правду расстояние будет получаться для объектов с одинаковой широтой.

Кратчайшее расстояние посчитать без привлечения сферической тригонометрии нельзя даже для городов, лежащих на одной широте.

Не важно. Мне надо найти объекты в радиусе от определенной точки. Это всё достаточно условно. И измеряется восновном в радиусе 100-10000 метров.

Точки хранятся в базе SQL - их десятки тысяч. Провести над ними тригонометрическую операцию темболее внутри SQL запроса представляется невозможным. А с простым умножением выборка проходит очень быстро.

А вообще разве декартовы координаты (частным случаем которыхх являются пиксельные) введены в систему разве не для подобного упрощения расчётов??

Дело в том, что преобразование географические координаты декартовые не сохраняет расстояние; в меркаторовской проекции карта тянется к полюсам.

Т.о. круг на экране монитора будет представлять собой какую-то кривую на глобусе и наоборот.

А чем вас не устраивает вариант "выбрать все точки в радиусе меньше 1000 пикселей", если вам не важна точность на больших расстояниях?

Заказчику необходимы метры. Представляете себе отчёт маркетолога: "продажи в зоне 1000 пикселей от центра города составляют. " )))

Ну, если очень приближённо, то плотность пикселы/метр вычисляется примерно так:

256 * 2^^17 / (40075016 * cos(lat))

256 * 2^^17 = 2^^25 - ширина "мира" в пикселах

40075016 - длина экватора в метрах. На широте lat длина параллели равна 40075016 * cos(lat)

Широта здесь в радианах. Косинус база считать умеет?

Да, умеет. Попробую как это получится. Хотя на десятках тысяч записей такой запрос будет выполняться существенно долбше умножения (

Читайте также: