快速检索来自数千张图像的exif数据-优化功能

时间:2019-02-13 13:31:34

标签: python-3.x performance function exif

我编写的脚本可以从目录(包括子目录)中的数千个图像中检索exif数据的特定字段,并将信息保存到csv文件中:

import os
from PIL import Image
from PIL.ExifTags import TAGS
import csv
from os.path import join

####SET THESE!###
imgpath = 'C:/x/y' #Path to folder of images
csvname = 'EXIF_data.csv' #Name of saved csv
###

def get_exif(fn):
    ret = {}
    i = Image.open(fn)
    info = i._getexif()
    for tag, value in info.items():
        decoded = TAGS.get(tag, tag)
        ret[decoded] = value
    return ret

exif_list = []
path_list = []
filename_list = []
DTO_list = []
MN_list = []

for root, dirs, files in os.walk(imgpath, topdown=True):
   for name in files:
       if name.endswith('.JPG'):
           pat = join(root, name)
           pat.replace(os.sep,"/")
           exif = get_exif(pat)
           path_list.append(pat)
           filename_list.append(name)
           DTO_list.append(exif['DateTimeOriginal'])
           MN_list.append(exif['MakerNote'])   

zipped = zip(path_list, filename_list, DTO_list, MN_list)

with open(csvname, "w", newline='') as f:
    writer = csv.writer(f)
    writer.writerow(('Paths','Filenames','DateAndTime','MakerNotes'))
    for row in zipped:
        writer.writerow(row)

但是,它非常慢。我已经尝试通过使用列表和字典理解来优化脚本的性能和可读性。

import os
from os import walk #Necessary for recursive mode
from PIL import Image #Opens images and retrieves exif
from PIL.ExifTags import TAGS #Convert exif tags from digits to names
import csv #Write to csv
from os.path import join #Join directory and filename for path

####SET THESE!###
imgpath = 'C:/Users/au309263/Documents/imagesorting_testphotos/Finse/FINSE01' #Path to folder of images. The script searches subdirectories as well
csvname = 'PLC_Speedtest2.csv' #Name of saved csv
###

def get_exif(fn): #Defining a function that opens an image, retrieves the exif data, corrects the exif tags from digits to names and puts the data into a dictionary
    i = Image.open(fn)   
    info = i._getexif()
    ret = {TAGS.get(tag, tag): value for tag, value in info.items()} 
    return ret

Paths = [join(root, f).replace(os.sep,"/") for root, dirs, files in walk(imgpath, topdown=True) for f in files if f.endswith('.JPG' or '.jpg')] #Creates list of paths for images
Filenames = [f for root, dirs, files in walk(imgpath, topdown=True) for f in files if f.endswith('.JPG' or '.jpg')] #Creates list of filenames for images
ExifData = list(map(get_exif, Paths)) #Runs the get_exif function on each of the images specified in the Paths list. List converts the map-object to a list.
MakerNotes = [i['MakerNote'] for i in ExifData] #Creates list of MakerNotes from exif data for images
DateAndTime = [i['DateTimeOriginal'] for i in ExifData] #Creates list of Date and Time from exif data for images

zipped = zip(Paths, Filenames, DateAndTime, MakerNotes) #Combines the four lists to be written into a csv.

with open(csvname, "w", newline='') as f: #Writes a csv-file with the exif data
    writer = csv.writer(f)
    writer.writerow(('Paths','Filenames','DateAndTime','MakerNotes'))
    for row in zipped:
        writer.writerow(row)

但是,这并没有改变性能。

我对代码的特定区域进行了计时,发现在get_exif函数中专门打开每个图像并从每个图像获取exif数据是需要时间的。 为了使脚本更快,我想知道是否: 1)可以优化函数的性能吗?,2)无需打开图像就可以检索exif数据吗?,3)list(map(fn,x))是应用该功能的最快方法?

1 个答案:

答案 0 :(得分:0)

如果以正确的方式阅读文档,PIL.Image.open()不仅会从文件中提取EXIF数据,还会读取并解码整个图像,这可能是这里的瓶颈。我要做的第一件事将是更改为仅对EXIF数据起作用且不关心图像内容的库或例程。 ExifReadpiexif可能值得一试。