本文介绍如何从 iPhone 照片库中提取 EXIF 数据,并将它们放入数据库,检索各种有趣的照片结果。
本文翻译自 Exploring EXIF,作者:harley turan, 略有删改。
根据iOS的照片应用程序数据,在过去的14年里,我已经拍摄了73,281张iPhone照片。
这些图像中的每一张照片不仅仅包含你在照片应用程序中滚动时看到的照片,它还包含了大量直接存储在图像文件本身中的编码信息。它详细介绍了有用的元数据,如照片拍摄的地点(以便您以后可以在地图上查看照片),拍摄图像的时间和日期,所使用的透镜和变焦级别,曝光,ISO和光圈,以及许多其他信息。
有很多工具中可以查看这些信息。你用来管理照片的应用程序将在图像旁边显示此元数据,例如在iOS 16中:
此元数据称为EXIF(可交换图像文件格式),存储在照片文件本身内部,出现在图像的开头(在任何图像数据出现之前)。如果我们检查从iPhone导出的JPEG照片的内容,我们会看到EXIF数据标记(FFE1)直接出现在JPEG图像开始标记(FFD8)之后:
这篇文章不会解释上面图片中的每个字节上。我们将研究照片包含什么,以及我们可以显示、查询和与其中的数据进行交互的各种方式。
照片里有什么
下面的图片显示了存储在单个图像中的大量元数据信息(因内容较多,只截图展示了部分数据)。EXIF数据解析由Mattias Wallander
的ExifReader
库处理。
每一张图像都是一个密集的信息球。不仅图像本身,还包含您在给拍摄那一刻的确切位置和方向等其他数据。
访问元数据
正如我们上面看到的照片包含了很多信息。在一个包含数千张图像的照片库中提取和查询数百个字段可能很棘手。幸运的是有很多工具可以帮助我们完成这项任务。
exiftool
就是一个很不错的选择,强烈建议使用这个工具。
为了存储和查询照片,我们将使用sqlite
。它适合我们的目的是有足够的性能完成此任务。
首先安装它们,如果您使用的是Mac,请使用brew
:
brew install sqlite3 exiftool
如果您使用的是
Apple Photos
,这里有两个选择:导出完整的照片图库,然后在输出的目录运行exiftool
,或者直接在Apple Photos
在后台使用的生成缩略图上运行exiftool
。如果你只是想要一种快速的方法来为你的
Apple Photos
库生成一套完整的EXIF数据,我发现以下方法在2023年8月之前效果很好。它解析内部derivatives
目录中的低分辨率缩略图(以_c.jpeg结尾的缩略图):
bashexiftool -n -csv -r ~/Pictures/Photos\ Library.photoslibrary/resour>ces/derivatives -i ~/Pictures/Photos\ Library.photoslibrary/resourc>es/derivatives/masters -if '$Filename=~/_c.jpeg/i' > exif.csv
从Apple Photos
中提取一组照片可能会非常棘手。图像的底层架构和存储其中许多包含远程存储在iCloud中的原件,需要专业工具来解析。您可以使用osxphotos
这个工具,它以任何格式导出完整的Apple Photo
图库,并且像--added-in-last "1 month"
这样的参数可以进行详细的过滤。下面是一个示例:
css
osxphotos export --added-in-last "1 month" --only-photos --not-edited --exif Model iPhone ./export
一旦我们有了一个图像目录,我们就可以使用exiftool
将元数据提取到CSV中。
bash
exiftool -n -m -csv ./images > exif.csv
然后将此CSV导入sqlite
进行查询。
shell
sqlite exif.db
sqlite> .mode csv
sqlite> .import exif.csv photos
sqlite> SELECT count(*) FROM photos;
68182
现在我们有了一个数据库,里面有我们拍摄过的每一张照片的可查询元数据。接下来让我们问这些数据一些问题吧!
感兴趣的字段
在浏览丰富的元数据时,有些字段对我来说很突出。其中一些是EXIF标准,但更多是针对Apple相机的:
视野 (FOV) :图像捕获时的水平视野。
方向/航向 (GPSImgDirection) :沿着位置(纬度和经度),EXIF还存储有关捕获图像时相机指向何处的信息。这与相机的视野相结合,使我们能够用视觉锥来注释图片在的地图位置。
海拔 (GPSAltitudeRef) :图像的高度虽然通常不精确,但可用于将3D数据给予2D纬度/经度对。这种额外的尺寸在多层建筑物和结构中或在空中时很有用。
速度 (GPSSpeed) :拍摄图像时相机移动的速度。
仰角(CameraElevationAngle) :如果有足够的精度,当与来自x,y,z、GPSLatitude
和GPSLongitude
的空间中的GPSAltitudeRef
点和来自GPSImgDirection
的1D角度相结合时,我们可以在给定的时间点通过空间发射3D向量。
图像噪声(SignalToNoiseRatio) :信号量与相机传感器捕捉到的噪声。可用于表示图像质量。
摄像头正常运行时间(RunTimeValue) :摄像机自上次开机以来已运行了多长时间。
焦点(FocusDistance & FocusPosition) :图像聚焦时与照相机的距离。
摄像机加速(AccelerationVector) :一个三维矢量,显示相机的向前/向后、向上/向下和左右加速度。
基于这些字段我们可以对照片数据库提出一些有趣的问题。
哪张照片有最多的面孔?
vbnet
SELECT SourceFile
FROM photos
WHERE RegionType IS NOT ''
ORDER BY length(RegionType) DESC
LIMIT 1;
哪些照片的拍摄对象离得太近以至于无法对焦?
sql
SELECT SourceFile
FROM photos
WHERE CAST(FocusPosition AS INT) IS 255
LIMIT 10;
开机后到拍照前最短的时间是多少?
sql
SELECT SourceFile
FROM photos
WHERE CAST(RunTimeValue AS INT) > 0
ORDER BY CAST(RunTimeValue as INT) ASC
LIMIT 1;
我有多少张照片是我以超过50英里每小时的速度拍摄的?
sql
SELECT count(*)
FROM photos
WHERE CAST(GPSSpeed AS REAL) > 50;
// 317
我拍的最快的照片是哪一张?
sql
SELECT SourceFile
FROM photos
ORDER BY CAST(GPSSpeed AS REAL) DESC
LIMIT 1;
我在陆地上拍的最快的照片是哪一张?
sql
SELECT SourceFile
FROM photos
WHERE CAST(GPSAltitude AS REAL) < 10
ORDER BY CAST(GPSSpeed AS REAL) DESC
LIMIT 1;
给我看日落的照片
sql
SELECT SourceFile
FROM photos
WHERE CAST(GPSImgDirection AS INT) BETWEEN 225 AND 315
AND time(TimeCreated) BETWEEN time('16:00') AND time('20:00')
AND CAST(FocusPosition AS INT) = 0
ORDER BY CAST(SignalToNoiseRatio as REAL) DESC
LIMIT 10;
这里的结果将根据您的位置而有所不同。这可以使用
lat/long
和一年中的时间来进一步增强以精确地将时间范围调整到日落。
我手机掉下的时候有什么照片?
sql
SELECT SourceFile
FROM photos
ORDER BY CAST(substr(AccelerationVector, 0, instr(AccelerationVector, ' ')) AS REAL) ASC
LIMIT 10;
我照片里最远的脸是哪些?
scss
SELECT SourceFile
FROM photos
WHERE length(RegionAreaW) IS 20 AND length(RegionAreaH) IS 20
ORDER BY CAST(substr(RegionAreaW,0,20) AS REAL) * CAST(substr(RegionAreaH,0,20) AS REAL) ASC
LIMIT 10;
当我给他们拍照的时候,谁的头歪得最厉害?
sql
SELECT SourceFile
FROM photos
ORDER BY CAST(RegionExtensionsAngleInfoRoll AS REAL) ASC
LIMIT 1;
影响
当你在网上发布一张朋友公寓楼的照片时,你不仅仅提供了图像本身,你还提供了纬度、经度和海拔。凭借良好的GPS精度,完全有可能找到照片拍摄的确切公寓。
事实上当你给予一个iOS应用程序对你的照片库的完全访问权时,你也把所有这些信息都给了别人。任何可以访问你的照片库的应用程序都可以通过足够的努力确定你的地址,你在哪里购物,你的朋友住在哪里,你去哪里度假,你在哪里工作,以及你什么时候睡觉。这些都是不需要看图像本身而得来的数据。
看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~
专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)