某程序员中午在餐饮区看到女神和她几个同事在狂抱怨手机里的照片好久没整理,复制到电脑里有好几千张,今晚要熬夜整理。这货马上说,我以前写了个整理照片的脚本,几分钟就可以搞定。几个女人惊讶中,顺利和女神加了微信。
这货午觉也没睡,赶紧动手用Python写脚本,将所有的照片,按拍摄地点归类,并自动创建文件夹移动到相应的文件夹中。不说了,赶紧要过来收藏进我的恋爱素材库。
准备工作:
首先,在虚拟环境中安装识别图片元数据的库。
pip install exifread
然后,进入高德开放平台,申请一个 Web 服务的应用,获取一个 「Key」用于逆地理编码 API。
编写脚本:(4步骤)
- 获取图片的经度和纬度
- 对经度和纬度进行数据矫正、
- 调用高德逆地理编码 API 获取具体位置
- 根据获取的位置信息创建文件夹,把对应的照片存入其中
第 1 步,获取图片的「经度和纬度」。
使用 exifread 库可以直接读取图片文件,获取到图片的元数据,包含经度、纬度、南北纬方向、东西经方向和拍摄时间。
# 使用exifread获取图片的元数据
img_exif = exifread.process_file(open(self.img_path,'test'))
# 获取图片的经纬度和拍摄时间
if img_exif:
# 纬度
latitude = img_exif['GPS Latitude']
# 纬度方向 N,S
latitude_direction = img_exif['GPS LatitudeRef']
# 经度
longitude = img_exif['GPS Longitude']
# 经度方向 E,W
longitude_direction = img_exif['GPS LongitudeRef']
# 拍摄时间
shooting_time = img_exif['EXIF OriginalTime']
第2步,坐标转换
通过 GPS 获取的经度、纬度和高德地图的坐标存在一定的误差,这里需要把坐标转换为「火星坐标系」。
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626 # 圆周率Π
a = 6378245.0 # 长半轴
flattening = 0.00669342162296594323 # 扁率
def conversion_coordinate(lng, lat):
"""
WGS84转GCJ02(火星坐标系)
:param lng:WGS84坐标系的经度
:param lat:WGS84坐标系的纬度
:return:
"""
# 判断是否在国内
if isInChina(lng, lat):
return lng, lat
dlat = transformlat(lng - 105.0, lat - 35.0)
dlng = transformlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - flattening * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / (( a * (1 - flattening)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / ( a / sqrtmagic * math.cos(radlat) * pi)
mglat = lat + dlat
mglng = lng + dlng
return [mglng, mglat]
另外需要注意的是,接口中经度、纬度参数只能识别小数点后 6 位,需要对经纬度中的度、分、秒做一定的数据处理,然后再进行四舍五入。
def format_data(data):
"""
格式化经度和纬度数据,只保留6位小数
"""
# 删除括号、空格
data_list_tmp = str(data).replace('[', '').replace(']', '').split(',')
data_list = [data.strip() for data in data_list_tmp]
# 替换秒的值
data_tmp = data_list[-1].split('/')
# 秒
data_sec = int(data_tmp[0]) / int(data_tmp[1]) / 3600
# 替换分的值
data_tmp = data_list[-2]
# 分
data_minute = int(data_tmp) / 60
# 经纬度
data_degree = int(data_list[0])
# 高德地图API只能识别到小数点后的6位
# 需要转换为浮点数,且只保留6位小数
result = "%.6f" % (data_degree + data_minute + data_sec)
return float(result)
第 3 步,获取坐标地址
调用高德的反地理编码 API,转入申请的应用 Key,就能拿到照片的详细地址。
def get_address(location):
"""
根据坐标获取详细地址
:param location: 经纬度值
:return:
"""
resp = requests.get(url_get_position.format(api_key, location))
location_data = json.loads(resp.text)
address = location_data.get('regeocode').get('formatted_address')
return address
第4步,照片归位
根据获取的详细的地址信息,创建文件夹,把照片移到文件夹中
for img_path in img_path_list:
address = get_address(img_path)
(country, province, city) = get_city(address)
dir_path = create_dir(country, province, city)
move_pic(img_path, dir_path)
write_log(img_path)
结论:只要女神给你的图片是原图,就可以使用上述方式,按照拍照地点快速整理海量照片。