我可以get the EXIF data from an image使用PIL,但我怎样才能获得拍摄照片的日期和时间?
答案 0 :(得分:38)
最终找到了答案,我需要的标签是36867:
from PIL import Image
def get_date_taken(path):
return Image.open(path)._getexif()[36867]
答案 1 :(得分:11)
我喜欢使用<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:background="#283341"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_startup" tools:context=".StartupActivity">
<ImageView
android:id="@+id/startupImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginTop="150dp"
android:layout_centerInParent="true"
android:src="@drawable/q_orange" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:layout_marginBottom="30dp">
<ProgressBar
android:id="@+id/loadingSpinner"
style="?android:attr/progressBarStyleSmall"
android:layout_centerInParent="true"
android:layout_width="33dp"
android:layout_height="33dp"
android:visibility="visible"
android:indeterminate="true"
/>
<TextView
android:id="@+id/startupStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Loading..."
android:textColor="#ff8a07"
android:textSize="25sp" />
</LinearLayout>
</RelativeLayout>
,因为它是纯python,不需要编译/安装,并且兼容python 2.x和3.x,非常适合捆绑小型便携式python应用
链接: https://github.com/ianare/exif-py
获取照片拍摄日期和时间的示例:
exif-py
答案 2 :(得分:5)
ExifTags.TAGS
是从标记到标记名称的映射。您可以使用它来创建标记名称到值的映射。
在这张特定图片上,可以使用几种不同的“日期”属性(DateTime
,DateTimeOriginal
,DateTimeDigitized
)。
import json
from PIL import Image, ExifTags
from datetime import datetime
def main(filename):
image_exif = Image.open(filename)._getexif()
if image_exif:
# Make a map with tag names
exif = { ExifTags.TAGS[k]: v for k, v in image_exif.items() if k in ExifTags.TAGS and type(v) is not bytes }
print(json.dumps(exif, indent=4))
# Grab the date
date_obj = datetime.strptime(exif['DateTimeOriginal'], '%Y:%m:%d %H:%M:%S')
print(date_obj)
else:
print('Unable to get date from exif for %s' % filename)
输出:
{
"DateTimeOriginal": "2008:11:15 19:36:24",
"DateTimeDigitized": "2008:11:15 19:36:24",
"ColorSpace": 1,
"ExifImageWidth": 3088,
"SceneCaptureType": 0,
"ExifImageHeight": 2320,
"SubjectDistanceRange": 2,
"ImageDescription": " ",
"Make": "Hewlett-Packard ",
"Model": "HP Photosmart R740 ",
"Orientation": 1,
"DateTime": "2008:11:15 19:36:24",
...
}
2008-11-15 19:36:24
答案 3 :(得分:3)
try:
import PIL
import PIL.Image as PILimage
from PIL import ImageDraw, ImageFont, ImageEnhance
from PIL.ExifTags import TAGS, GPSTAGS
except ImportError as err:
exit(err)
class Worker(object):
def __init__(self, img):
self.img = img
self.get_exif_data()
self.date =self.get_date_time()
super(Worker, self).__init__()
def get_exif_data(self):
exif_data = {}
info = self.img._getexif()
if info:
for tag, value in info.items():
decoded = TAGS.get(tag, tag)
if decoded == "GPSInfo":
gps_data = {}
for t in value:
sub_decoded = GPSTAGS.get(t, t)
gps_data[sub_decoded] = value[t]
exif_data[decoded] = gps_data
else:
exif_data[decoded] = value
self.exif_data = exif_data
# return exif_data
def get_date_time(self):
if 'DateTime' in self.exif_data:
date_and_time = self.exif_data['DateTime']
return date_and_time
def main():
date = image.date
print(date)
if __name__ == '__main__':
try:
img = PILimage.open(path + filename)
image = Worker(img)
date = image.date
print(date)
except Exception as e:
print(e)
答案 4 :(得分:1)
在较新版本的Pillow(我认为6.0+)中,这一点已发生了轻微变化。
他们添加了您应该使用的公共方法getexif()
。先前的版本是私有的和实验性的(_getexif()
)。
from PIL import Image
im = Image.open('path/to/image.jpg')
exif = im.getexif()
creation_time = exif.get(36867)
答案 5 :(得分:1)
我创建了一个函数(get_exif
),可以更轻松地获取属性。
your_date_time: str = get_exif(Path('test.jpg'), 'DateTimeOriginal')
# your_date_time = get_exif(Path('test.jpg'), 0x9003) # same as above
from pathlib import Path
from typing import Union, List, Tuple
import PIL.Image
import PIL.ExifTags
def get_exif(file_path: Path,
search_list: Union[int, str, List, Tuple] = None,
ignore_error=True
) -> Union[int, PIL.Image.Exif, List]:
"""
:param file_path: image path
:param search_list: if you want to get some property, then you can pass the id or name, it will return by order.
:param ignore_error:
:return:
int: -1 FileNotFoundError, or exif is None
PIL.Image.Exif: when the `search_list` is None, return the whole Exif
"""
tag_by_id: dict = PIL.ExifTags.TAGS
try:
im: PIL.Image.Image = PIL.Image.open(str(file_path))
except FileNotFoundError:
if ignore_error:
return -1
else:
raise FileNotFoundError(file_path)
exif: PIL.Image.Exif = im.getexif()
if not exif:
if ignore_error:
return -1
else:
raise ValueError("exif is None")
if search_list is None:
return exif
tag_by_name = {tag_by_id[dec_value]: exif[dec_value] for dec_value in exif if dec_value in tag_by_id}
result_list = []
if not isinstance(search_list, (list, tuple)):
search_list = [search_list]
for key in search_list:
if isinstance(key, int):
result_list.append(exif.get(key, None))
continue
try:
dec_value = int(key, 16)
result_list.append(exif.get(dec_value, None))
continue
except ValueError:
...
result_list.append(tag_by_name.get(key, None))
return result_list if len(result_list) > 1 else result_list[0]
import unittest
class ExifTests(unittest.TestCase):
def test(self):
exif: PIL.Image.Exif = get_exif(Path('test.jpg')) # same as the ``PIL.Image.open().getexif()``
# get specify attribute only
date_t_ori1 = get_exif(Path('test.jpg'), 0x9003)
date_t_ori2 = get_exif(Path('test.jpg'), '0x9003', ) # hex string is ok too.
date_t_ori3 = get_exif(Path('test.jpg'), 'DateTimeOriginal') # Give name is also working.
self.assertTrue(date_t_ori1 == date_t_ori2 == date_t_ori3)
# You can get multiple values at once. If the key does not exist, it returns None.
date_t_ori4, img_length, _, __ = get_exif(Path('test.jpg'),
(36867, 'ImageLength', 'NoteExitName', -12345))
# Occurring error return -1 (by default ignore_error=True)
self.assertEqual(-1, get_exif(Path('not exist.jpg'))) # FileNotFoundError
self.assertEqual(-1, get_exif(Path('no_exif_tag.jpg'))) # ValueError
self.assertRaises(FileNotFoundError, get_exif, Path('not exist.jpg'), ignore_error=False)
self.assertRaises(ValueError, get_exif, Path('no_exif_tag.jpg'), ignore_error=False)
这个website很好,但是如果要获取完整列表,则应该引用PIL.ExifTags.py
,请参见下文,
# ExifTags.py
# Maps EXIF tags to tag names.
TAGS = {
# possibly incomplete
0x000B: "ProcessingSoftware",
0x00FE: "NewSubfileType",
0x00FF: "SubfileType",
0x0100: "ImageWidth",
0x0101: "ImageLength",
0x0102: "BitsPerSample",
...
0xA430: "CameraOwnerName", # <-- The website does not record it. (The website record last tag is A420.)
0xA431: "BodySerialNumber",
0xA432: "LensSpecification",
0xA433: "LensMake",
0xA434: "LensModel",
}
# Maps EXIF GPS tags to tag names.
GPSTAGS = {
0: "GPSVersionID",
1: "GPSLatitudeRef",
2: "GPSLatitude",
3: "GPSLongitudeRef",
4: "GPSLongitude",
5: "GPSAltitudeRef",
6: "GPSAltitude",
7: "GPSTimeStamp",
...
}
答案 6 :(得分:0)
从_getexif()返回的词典使用键&#39; DateTimeOriginal&#39;?