900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Python给照片添加水印时间和地点 Mac OS

Python给照片添加水印时间和地点 Mac OS

时间:2019-11-26 09:59:46

相关推荐

Python给照片添加水印时间和地点 Mac OS

这里写目录标题

效果需要用到的模块处理步骤以及代码讲解1、获得照片的拍摄时间2、获取拍照地点3、图片转正4、 添加水印完整代码

我们平时想打印图片的时候,希望能给照片加上时间、地点,以便以后看到照片的时候不会忘记。

手工一张张添加太麻烦,而且容易出错。以下是使用代码获取原始图片的拍摄时间和地点,并添加水印的方法,在Mac OS下对jpeg、jpg文件处理已经测试通过了。

效果

首先我们看下效果,第一张是原图,第二张是添加水印时间和地点后的图:

需要用到的模块

exifread

PIL

requests

json

处理步骤以及代码讲解

1、获得照片的拍摄时间

这里我们需要用到exifread模块以获取照片的拍照时间。1

def getPhotoTime(filename):'''得到照片的拍照时间(如果获取不到拍照时间,则使用文件的创建时间)'''try:if os.path.isfile(filename):fd = open(filename, 'rb')else:raise "[%s] is not a file!\n" % filenameexcept:raise "unopen file[%s]\n" % filename#默认用图像文件的创建日期作为拍摄日期(如果有照片的拍摄日期,则修改为拍摄日期state = os.stat(filename)dateStr = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(state[-2]))data = exifread.process_file( fd )if data: #取得照片的拍摄日期,改为拍摄日期try:t = data['EXIF DateTimeOriginal'] #转换成 yyyy-mm-dd_hh:mm:ss的格式dateStr = str(t).replace(":","-")[:10] + str(t)[10:]except:passreturn dateStr

2、获取拍照地点

这里我们依然要用到exifread模块以获取照片的拍照的经纬度,在使用baidu的api逆地理编码得到对应的具体位置。2

注意在使用baidu的api之前需要去百度地图开放平台注册账号,申请secret_key,可以参考别人的申请ak3。

def format_lat_lng(data):'将exif得到的经纬度转化成数值, 这个有点笨重'list_tmp=str(data).replace('[', '').replace(']', '').split(',')l= [ele.strip() for ele in list_tmp]data_sec = int(l[-1].split('/')[0]) /(int(l[-1].split('/')[1])*3600)# 秒的值data_minute = int(l[1])/60data_degree = int(l[0])result=data_degree + data_minute + data_secreturn resultdef getLocationBy_lat_lng(lat, lng):"""使用Geocoding API把经纬度坐标转换为结构化地址。需要注册baidu map api的key"""secret_key = 'XXXXX你得ak密钥' # 请修改这里# 使用说明/index.php?title=webapi/guide/webservice-geocoding-abroadbaidu_map_api = 'http://api./reverse_geocoding/v3/?ak={0}&output=json&coordtype=wgs84ll&location={1},{2}'.format(secret_key, lat, lng)response = requests.get(baidu_map_api)content = response.textbaidu_map_address = json.loads(content)formatted_address = baidu_map_address["result"]["formatted_address"]return formatted_addressdef getLocation(filename):'得到照片的拍照位置(如果获取不到,则为空字符串)'try:if os.path.isfile(filename):fd = open(filename, 'rb')else:raise "[%s] is not a file!\n" % filenameexcept:raise "unopen file[%s]\n" % filename# 图像文件的拍摄地址默认为空locationStr= ''data = exifread.process_file( fd )if data: #取得照片的拍摄位置try:lat= format_lat_lng(data['GPS GPSLatitude']) # [34, 12, 9286743/200000] -> xx.xxxxxlng= format_lat_lng(data['GPS GPSLongitude']) # [108, 57, 56019287/1000000] -> xx.xxxxlocationStr= getLocationBy_lat_lng(lat, lng)except:passreturn locationStr

3、图片转正

对于手机、相机等设备拍摄的照片,由于手持方向的不同,拍出来的照片可能是旋转0°、90°、180°和270°。即使在电脑上利用软件将其转正,他们的exif信息中还是会保留方位信息。

在用PIL读取这些图像时,读取的是原始数据,也就是说,即使电脑屏幕上显示是正常的照片,用PIL读进来后,也可能是旋转的图像,并且图片的size也可能与屏幕上的不一样。

对于这种情况,可以利用PIL读取exif中的orientation信息,然后根据这个信息将图片转正后,再进行后续操作,具体如下。4

def orientate(img):'''利用PIL读取exif中的orientation信息,然后根据这个信息将图片转正后,再进行后续操作'''try:orientation= Nonefor i in ExifTags.TAGS.keys() : if ExifTags.TAGS[i]=='Orientation' : # 肯定会找到orientation,所以不需要对None做处理orientation= ibreak exif=dict(img._getexif().items())if exif[orientation] == 3 : img=img.rotate(180, expand = True)elif exif[orientation] == 6 : img=img.rotate(270, expand = True)elif exif[orientation] == 8 : img=img.rotate(90, expand = True)except:passreturn img

4、 添加水印

最后是添加水印,这一步是将上面的步骤整合起来,做处理。

这一步根据不同的图片需要调整字体大小(size),字体位置(d_width,d_height)和字体填充颜色(fillcolor)。5

def add_watermark(filename, text):'为照片文件添加水印,filename是照片文件名,text是水印时间和位置'# 创建输出文件夹outdir= 'watermark/'mymkdir(outdir) # 创建绘画对象image= Image.open(filename)image= orientate(image) # 将图片转正draw= ImageDraw.Draw(image)width, height= image.size # 宽度,高度size= int(0.04*width) # 字体大小(可以调整0.04)myfont= ImageFont.truetype('/Library/Fonts/Arial Unicode.ttf', size=size) # 80, 4032*3024#fillcolor= '#000000' # RGB黑色fillcolor= '#fbfafe'# 参数一:位置(x轴,y轴);参数二:填写内容;参数三:字体;参数四:颜色 d_width, d_height=0.5*width, 0.92*height # 字体的相对位置(0.5, 0.92可以根据图片调整)draw.text((d_width, d_height), text, font=myfont, fill=fillcolor) # (-1200, -320)new_filename= get_new_filename(filename)image.save(outdir + new_filename)

完整代码

以下是完整代码,并附上github的链接(链接中有原始的示例图片)。

''' 批量给图片增加时间水印的Python脚本程序【目前测试为Mac OS X下的jpeg文件】。遍历指定目录(含子目录)的照片文件,根据拍照时间给照片在右下角添加时间和地点的水印。!该程序需要安装exifread,PIL,requests等模块,否则无法使用。例如,Linux/Mac OS X下命令行安装该模块:sudo pip install exifread!该程序需要加baidu api的secret_key(在getLocationBy_lat_lng函数中);!该程序可以手动调整字体大小(size),字体位置(d_width,d_height)和字体填充颜色(fillcolor)(在add_watermark函数中)。获取拍照时间 From '//05/14/python-script-to-change-pictures-filenames/'拍照地点 参考 /index.php?title=webapi/guide/webservice-geocoding-abroadwatermark 参考 /weixin_30561177/article/details/97609897 orientation 参考 /mizhenpeng/article/details/82794112'''#!/usr/bin/env python# -*- coding: utf-8 -*- import osimport statimport timeimport mathimport exifreadfrom PIL import Image, ImageDraw, ImageFont, ExifTagsimport requestsimport json'=================分割线==================='# 创建文件夹def mymkdir(path):if not os.path.exists(path):os.mkdir(path)# 判断是否是支持的文件类型SUFFIX_FILTER = ['.jpg','.png','.mpg','.mp4','.thm','.bmp','.jpeg','.avi','.mov'] # 仅测试了jpeg,jpgdef isTargetedFileType(filename):'根据文件扩展名,判断是否是需要处理的文件类型;仅支持x.x格式'filename_nopath = os.path.basename(filename)f,e = os.path.splitext(filename_nopath)if e.lower() in SUFFIX_FILTER:return Trueelse:return False# 新文件的名字def get_new_filename(filename):f, e= filename.split('.')return "%s_watermark.%s" % (f, e)'=================分割线===================''=================begin{得到照片的拍摄时间}==================='def getPhotoTime(filename):'''得到照片的拍照时间(如果获取不到拍照时间,则使用文件的创建时间)'''try:if os.path.isfile(filename):fd = open(filename, 'rb')else:raise "[%s] is not a file!\n" % filenameexcept:raise "unopen file[%s]\n" % filename#默认用图像文件的创建日期作为拍摄日期(如果有照片的拍摄日期,则修改为拍摄日期state = os.stat(filename)dateStr = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(state[-2]))data = exifread.process_file( fd )if data: #取得照片的拍摄日期,改为拍摄日期try:t = data['EXIF DateTimeOriginal'] #转换成 yyyy-mm-dd_hh:mm:ss的格式dateStr = str(t).replace(":","-")[:10] + str(t)[10:]except:passreturn dateStr'=================end{得到照片的拍摄时间}===================''=================begin{得到照片的拍摄地点}==================='def format_lat_lng(data):'将exif得到的经纬度转化成数值, 这个有点笨重'list_tmp=str(data).replace('[', '').replace(']', '').split(',')l= [ele.strip() for ele in list_tmp]data_sec = int(l[-1].split('/')[0]) /(int(l[-1].split('/')[1])*3600)# 秒的值data_minute = int(l[1])/60data_degree = int(l[0])result=data_degree + data_minute + data_secreturn resultdef getLocationBy_lat_lng(lat, lng):"""使用Geocoding API把经纬度坐标转换为结构化地址。需要注册baidu map api的key"""secret_key = 'XXXXX你得ak密钥' # 请修改这里# 使用说明/index.php?title=webapi/guide/webservice-geocoding-abroadbaidu_map_api = 'http://api./reverse_geocoding/v3/?ak={0}&output=json&coordtype=wgs84ll&location={1},{2}'.format(secret_key, lat, lng)response = requests.get(baidu_map_api)content = response.textbaidu_map_address = json.loads(content)formatted_address = baidu_map_address["result"]["formatted_address"]return formatted_addressdef getLocation(filename):'得到照片的拍照位置(如果获取不到,则为空字符串)'try:if os.path.isfile(filename):fd = open(filename, 'rb')else:raise "[%s] is not a file!\n" % filenameexcept:raise "unopen file[%s]\n" % filename# 图像文件的拍摄地址默认为空locationStr= ''data = exifread.process_file( fd )if data: #取得照片的拍摄位置try:lat= format_lat_lng(data['GPS GPSLatitude']) # [34, 12, 9286743/200000] -> xx.xxxxxlng= format_lat_lng(data['GPS GPSLongitude']) # [108, 57, 56019287/1000000] -> xx.xxxxlocationStr= getLocationBy_lat_lng(lat, lng)except:passreturn locationStr'=================end{得到照片的拍摄地点}==================='def orientate(img):'''对于手机、相机等设备拍摄的照片,由于手持方向的不同,拍出来的照片可能是旋转0°、90°、180°和270°。即使在电脑上利用软件将其转正,他们的exif信息中还是会保留方位信息。在用PIL读取这些图像时,读取的是原始数据,也就是说,即使电脑屏幕上显示是正常的照片,用PIL读进来后,也可能是旋转的图像,并且图片的size也可能与屏幕上的不一样。对于这种情况,可以利用PIL读取exif中的orientation信息,然后根据这个信息将图片转正后,再进行后续操作,具体如下。'''try:orientation= Nonefor i in ExifTags.TAGS.keys() : if ExifTags.TAGS[i]=='Orientation' : # 肯定会找到orientation,所以不需要对None做处理orientation= ibreak exif=dict(img._getexif().items())if exif[orientation] == 3 : img=img.rotate(180, expand = True)elif exif[orientation] == 6 : img=img.rotate(270, expand = True)elif exif[orientation] == 8 : img=img.rotate(90, expand = True)except:passreturn imgdef add_watermark(filename, text):'为照片文件添加水印,filename是照片文件名,text是水印时间和位置'# 创建输出文件夹outdir= 'watermark/'mymkdir(outdir) # 创建绘画对象image= Image.open(filename)image= orientate(image) # 将图片转正draw= ImageDraw.Draw(image)width, height= image.size # 宽度,高度size= int(0.04*width) # 字体大小(可以调整0.04)myfont= ImageFont.truetype('/Library/Fonts/Arial Unicode.ttf', size=size) # 80, 4032*3024#fillcolor= '#000000' # RGB黑色fillcolor= '#fbfafe'# 参数一:位置(x轴,y轴);参数二:填写内容;参数三:字体;参数四:颜色 d_width, d_height=0.5*width, 0.92*height # 字体的相对位置(0.5, 0.92可以根据图片调整)draw.text((d_width, d_height), text, font=myfont, fill=fillcolor) # (-1200, -320)new_filename= get_new_filename(filename)image.save(outdir + new_filename)def scandir(startdir):'遍历指定目录,对满足条件的文件进行改名或删除处理'os.chdir(startdir) # 改变当前工作目录for obj in os.listdir(os.curdir) :if os.path.isfile(obj):if isTargetedFileType(obj): # 对满足过滤条件的文件,加时间和地点水印photoTime = getPhotoTime(obj) # 获得照片的拍摄时间,当作水印的内容location= getLocation(obj) # 获得照片的拍摄位置,当作水印的内容print("%s %s" % (obj, photoTime+' '+location))add_watermark(obj, location +'\n'+ photoTime) #加时间和地点水印if __name__ == "__main__":path = "./fig" # 照片位置scandir(path)

//05/14/python-script-to-change-pictures-filenames/ ↩︎

/index.php?title=webapi/guide/webservice-geocoding-abroad ↩︎

/p/6ad61317d988 ↩︎

/mizhenpeng/article/details/82794112 ↩︎

/weixin_30561177/article/details/97609897 ↩︎

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。