Author: Xing Anguo
Derived from:
I used Python to sneak up on my girlfriend behind her back
The target scene
Sometimes my girlfriend plays outside alone and asks her where she is, but won’t tell me. But what if you want to know where your girlfriend is?In fact, you can do this to your girlfriend, pretend that you are bored at home, you can help her edit the picture, ask her wechat to send you the original picture, after getting the “wechat original picture”, you can use Python to quickly get the specific location of your girlfriend.
The preparatory work
First, install a library that recognizes image metadata in your virtual environment.
pip3 install exifreadCopy the code
Then, enter autonavi open platform, apply for a Web service application, and obtain a “Key” for reverse geocoding API.
Write a script
The whole operation is divided into three steps, namely, obtaining the longitude and latitude of the image, correcting the longitude and latitude data, and calling Autonavi inverse geocoding API to obtain the specific location.
Step 1: Get the longitude and latitude of the image.
Using the Exifread library, you can directly read the image file and obtain the metadata of the image, including the longitude, latitude, north and south latitude, east and west longitude and the time when the image was taken.
Use exifread to retrieve image metadata
img_exif = exifread.process_file(open(self.img_path, 'rb'))
Properties can be read
if img_exif:
# number of latitude
latitude_gps = img_exif['GPS GPSLatitude']
# N,S in north and south latitudes
latitude_direction = img_exif['GPS GPSLatitudeRef']
# the degree
longitude_gps = img_exif['GPS GPSLongitude']
# E,W east-west longitude
longitude_direction = img_exif['GPS GPSLongitudeRef']
# Shooting time
take_time = img_exif['EXIF DateTimeOriginal']Copy the code
If metadata exists, then determine if the shooting time is reasonable. If it’s not today, I’m sorry to inform you that your girlfriend is lying to you.
def judge_time_met(self, take_time):
"""Param take_time: :return:"""
# Shooting time
format_time = str(take_time).split("")[0].replace(":"."-")
# Date of the day
today = str(datetime.date.today())
if format_time == today:
return True
else:
return False
if is_lie:
print('SORRY to inform you that your girlfriend is lying!! ')
returnCopy the code
If she is not lying, go to step 2.
Because there is some error in longitude, latitude and coordinates of Amap obtained by GPS, the coordinates need to be converted to “Mars coordinate system”.
X_pi = 3.14159265358979324 * 3000.0/180.0 PI = 3.1415926535897932384626# PI.A = 6378245.0# semi-major axisEe = 0.00669342162296594323# flat rate
def wgs84togcj02(lng, lat):
"""WGS84 to GCJ02(Mars coordinates) : Param LNG: Longitude of WGS84 coordinates: Param Lat: latitude of WGS84 coordinates :return:"""
if out_of_china(lng, lat): # Determine if it is in the country
returnLNG, LAT DLAT = TransformLAT (LNG-105.0, LAT-35.0) DLNG = TransformLLNG (LNG-105.0, LAT-35.0) Lat-35.0) radlat = Lat / 180.0 * PI magic = math.sin(radlat) magic = 1 - EE * magic * magic sqrtMagic = Math.sqrt (magic) dlAT = (dlAT * 180.0)/((a * (1-EE))/(Magic * SQrtMagic) * PI) DLNG = (DLNG * 180.0)/(a / sqrtmagic * math.cos(radlat) * pi) mglat = lat + dlat mglng = lng + dlngreturn [mglng, mglat]Copy the code
In addition, the longitude and latitude parameters in the interface can identify only six decimal places. You need to perform certain data processing for degrees, minutes, and seconds in the longitude and latitude before rounding them off.
def __format_lati_long_data(self, data):
""Param data: original latitude and longitude values :return:""
Delete the left and right parentheses and Spaces
data_list_tmp = str(data).replace('['.' ').replace('] '.' ').split(', ')
data_list = [data.strip() for data in data_list_tmp]
# Replace the value of seconds
data_tmp = data_list[-1].split('/')
The value of # s
data_sec = int(data_tmp[0]) / int(data_tmp[1]) / 3600
# Replace the value of the score
data_tmp = data_list[-2]
The value of # points
data_minute = int(data_tmp) / 60
The value of the # degrees
data_degree = int(data_list[0])
# Because the Autonavi API can only recognize 6 decimal places
# needs to be converted to a floating point number and retained as a 6-digit decimal
result = "%.6f" % (data_degree + data_minute + data_sec)
return float(result)Copy the code
Step 3: Call Autonavi’s anti-geocoding API, pass in the application Key, and get the detailed address of your girlfriend.
def __get_address(self, location):
""Param location: latitude and longitude value :return:""
resp = requests.get(self.url_get_position.format(self.api_key, location))
location_data = json.loads(resp.text)
address = location_data.get('regeocode').get('formatted_address')
return addressCopy the code
The complete code
main.py
import os
import exifread
from decimal import Decimal
from position_utils import *
import requests
import json
import datetime
# pip3 install exifread
class Location(object):
def __init__(self, image_path):
self.img_path = image_path
self.api_key = "The AK you applied for"
self.url_get_position = 'https://restapi.amap.com/v3/geocode/regeo?key={}&location={}'
def run(self):
coordinate = self.__get_image_ability()
print(f'Get longitude and latitude is {coordinate}'.)
if not coordinate:
return
Obtain the detailed address according to longitude and latitude
address = self.__get_address(coordinate)
# Check coordinate values
# https://lbs.amap.com/console/show/picker
print(f'Your girlfriend is at :{address}')
def __get_address(self, location):
""Param location: latitude and longitude value :return:""
resp = requests.get(self.url_get_position.format(self.api_key, location))
location_data = json.loads(resp.text)
address = location_data.get('regeocode').get('formatted_address')
return address
def __format_lati_long_data(self, data):
""Param data: original latitude and longitude values :return:""
Delete the left and right parentheses and Spaces
data_list_tmp = str(data).replace('['.' ').replace('] '.' ').split(', ')
data_list = [data.strip() for data in data_list_tmp]
# Replace the value of seconds
data_tmp = data_list[-1].split('/')
The value of # s
data_sec = int(data_tmp[0]) / int(data_tmp[1]) / 3600
# Replace the value of the score
data_tmp = data_list[-2]
The value of # points
data_minute = int(data_tmp) / 60
The value of the # degrees
data_degree = int(data_list[0])
# Because the Autonavi API can only recognize 6 decimal places
# needs to be converted to a floating point number and retained as a 6-digit decimal
result = "%.6f" % (data_degree + data_minute + data_sec)
return float(result)
def __get_image_ability(self):
"""Param picture_name: :return:"""
# Use the exifread library to read the attributes of the image
img_exif = exifread.process_file(open(self.img_path, 'rb'))
Properties can be read
if img_exif:
# number of latitude
latitude_gps = img_exif['GPS GPSLatitude']
# N,S in north and south latitudes
latitude_direction = img_exif['GPS GPSLatitudeRef']
# the degree
longitude_gps = img_exif['GPS GPSLongitude']
# E,W east-west longitude
longitude_direction = img_exif['GPS GPSLongitudeRef']
# Shooting time
take_time = img_exif['EXIF DateTimeOriginal']
is_lie = self.judge_time_met(take_time)
if is_lie:
print('SORRY to inform you that your girlfriend is lying!! ')
return
# Latitude, longitude, shooting time
if latitude_gps and longitude_gps and take_time:
The original values of latitude and longitude are further processed
latitude = self.__format_lati_long_data(latitude_gps)
longitude = self.__format_lati_long_data(longitude_gps)
# print(f'{longitude},{latitude}')
# Note: Since the coordinates obtained by GPS are not accurately inverse encoded on mainstream maps such as Autonavi in China, they need to be converted to Mars coordinate system
location = wgs84togcj02(longitude, latitude)
return f'{location[0]},{location[1]}'
else:
print(f'Incomplete image data properties obtained')
return ' '
else:
print('Sorry, the image is not the original image, can't get image properties. ')
return ' '
def judge_time_met(self, take_time):
"""Param take_time: :return:"""
# Shooting time
format_time = str(take_time).split("")[0].replace(":"."-")
# Date of the day
today = str(datetime.date.today())
if format_time == today:
return False
else:
return True
if __name__ == '__main__':
# My girlfriend sent me the picture [original picture]
location = Location('./picture/11441566648796_.pic_hd.jpg')
# Find your girlfriend's location
location.run()Copy the code
position_utils.py
Import json import math x_pi = 3.14159265358979324 * 3000.0/180.0 PI = 3.1415926535897932384626# PI.A = 6378245.0# semi-major axisEe = 0.00669342162296594323# flat rate
def wgs84togcj02(lng, lat):
"""WGS84 to GCJ02(Mars coordinates) : Param LNG: Longitude of WGS84 coordinates: Param Lat: latitude of WGS84 coordinates :return:"""
if out_of_china(lng, lat): # Determine if it is in the country
returnLNG, LAT DLAT = TransformLAT (LNG-105.0, LAT-35.0) DLNG = TransformLLNG (LNG-105.0, LAT-35.0) Lat-35.0) radlat = Lat / 180.0 * PI magic = math.sin(radlat) magic = 1 - EE * magic * magic sqrtMagic = Math.sqrt (magic) dlAT = (dlAT * 180.0)/((a * (1-EE))/(Magic * SQrtMagic) * PI) DLNG = (DLNG * 180.0)/(a / sqrtmagic * math.cos(radlat) * pi) mglat = lat + dlat mglng = lng + dlngreturn [mglng, mglat]
def gcj02towgs84(lng, lat):
"""GCJ02(Mars coordinates) to GPS84: Param LNG: Longitude of Mars coordinates: Param Lat: Latitude of Mars coordinates :return:"""
if out_of_china(lng, lat):
returnLNG, LAT DLAT = TransformLAT (LNG-105.0, LAT-35.0) DLNG = TransformLLNG (LNG-105.0, LAT-35.0) Lat-35.0) radlat = Lat / 180.0 * PI magic = math.sin(radlat) magic = 1 - EE * magic * magic sqrtMagic = Math.sqrt (magic) dlAT = (dlAT * 180.0)/((a * (1-EE))/(Magic * SQrtMagic) * PI) DLNG = (DLNG * 180.0)/(a / sqrtmagic * math.cos(radlat) * pi) mglat = lat + dlat mglng = lng + dlngreturn[lng * 2 - mglng, lat * 2 - mglat] def transformlat(lng, lat): Ret = -100.0 + 2.0 * LNG + 3.0 * Lat + 0.2 * Lat * Lat + \ 0.1 * LNG * lat + 0.2 * math.sqRT (math.fabs(LNG)) RET += (20.0 * math.sin(6.0 * LNG * PI) + 20.0 * math.sin(2.0 * LNG * PI)) * 2.0/3.0 ret += (20.0 * Math. sin(Lat * PI) + 40.0 * math.sin(lat / 3.0 * PI)) * 2.0/3.0 ret += (160.0 * math.sin(lat / 12.0 * PI) + 320 * math.sin(lat * PI / 30.0)) * 2.0/3.0returnret def transformlng(lng, lat): Ret = 300.0 + LNG + 2.0 * Lat + 0.1 * LNG * LNG + \ 0.1 * LNG * Lat + 0.1 * math.sqRT (math.fabs(LNG)) RET += (20.0 * Math. sin(6.0 * LNG * PI) + 20.0 * math.sin(2.0 * LNG * PI)) * 2.0/3.0 ret += (20.0 * Math. sin(LNG * PI) + 40.0 * Math. sin(LNG / 3.0 * PI)) * 2.0/3.0 ret += (150.0 * math.sin(LNG / 12.0 * PI) + 300.0 * math.sin(LNG / 30.0 * PI)) * 2.0/3.0return ret
def out_of_china(lng, lat):
"""Check whether it is in China or not :param LNG: : Param lat: :return:"""
ifLNG < 72.004 or LNG > 137.8347:return True
ifLat < 0.8293 or LAT > 55.8271:return True
return FalseCopy the code
Results the conclusion
Make sure the picture is the original one and you can quickly tell if your girlfriend is lying. If she is not lying, return to her specific location.
PS: All of this has a premise, that you have to have a girlfriend first!