照片EXIF数据统计与可视化

拍的照片越来越多,想要了解一下日常拍摄的习惯,便于后面换镜头、调整参数等操作,所以写了这个脚本来统计照片的EXIF数据。该脚本用于统计指定文件夹下所有JPG图片的EXIF数据,包括快门速度、ISO、焦距、光圈和拍摄时间,并生成相应的分布图。在使用时,需要将文中的代码段都粘贴到同一个文件中,然后修改folder_path变量为你要处理的文件夹路径,运行脚本即可。以下是脚本的详细说明。

依赖

  • Python 3.x
  • exifread库:用于读取图片的EXIF数据
  • matplotlib库:用于绘制分布图
  • numpy库:用于处理数值数据
  • pathlib库:用于处理文件路径
  • collections.Counter:用于统计频率

安装依赖

使用以下命令安装所需的Python库:

pip install exifread matplotlib numpy

使用方法

  1. 将脚本保存为photo_statistic.py
  2. 修改脚本中的folder_path变量,设置为你要处理的文件夹路径。
  3. 运行脚本:
python photo_statistic.py

代码说明

导入依赖

from pathlib import Path
import exifread
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
from collections import Counter

获取EXIF数据

get_exif_data函数用于读取图片的EXIF数据,并提取快门速度、ISO、焦距、光圈和拍摄时间。

def get_exif_data(image_path):with open(image_path, 'rb') as f:tags = exifread.process_file(f)shutter_speed = tags.get('EXIF ExposureTime') or tags.get('EXIF ShutterSpeedValue')iso = tags.get('EXIF ISOSpeedRatings')focal_length = tags.get('EXIF FocalLength')aperture = tags.get('EXIF FNumber') or tags.get('EXIF ApertureValue')datetime = tags.get('EXIF DateTimeOriginal') or tags.get('Image DateTime')return {'file': image_path,'shutter_speed': shutter_speed,'iso': iso,'focal_length': focal_length,'aperture': aperture,'datetime': datetime}

处理文件夹中的图片

process_images_in_folder函数遍历指定文件夹下的所有JPG图片,并调用get_exif_data函数获取每张图片的EXIF数据。

def process_images_in_folder(folder_path):results = []folder = Path(folder_path)for image_path in folder.rglob('*.jpg'):results.append(get_exif_data(image_path))return results

绘制统计图

plot_statistics函数用于绘制快门速度、ISO、焦距和光圈的分布图,并统计指定焦距的时间分布。

def plot_statistics(results):shutter_speeds = [float(result['shutter_speed'].values[0]) for result in results if result['shutter_speed']]isos = [int(result['iso'].values[0]) for result in results if result['iso']]focal_lengths = [float(result['focal_length'].values[0].num) / float(result['focal_length'].values[0].den) for result in results if result['focal_length']]apertures = [float(result['aperture'].values[0].num) / float(result['aperture'].values[0].den) for result in results if result['aperture']]dates = [result['datetime'].values.split(' ')[0].replace(':', '.') for result in results if result['datetime']]# 删除快门速度大于阈值的数据shutter_speeds_thres = 0.1shutter_speeds = [speed for speed in shutter_speeds if speed <= shutter_speeds_thres]fig, axs = plt.subplots(2, 1)# 将快门速度转换为分数格式def format_shutter_speed(speed):return (f"1/{(1/speed):.0f}" if speed != 0 else "0") if speed < 1 else str(speed)# 绘制快门速度分布图并将x轴刻度标签设置为分数格式axs[0].hist(shutter_speeds, bins=100, color='blue', edgecolor='black')axs[0].set_title('Shutter Speed Distribution' + f' (Threshold: {shutter_speeds_thres}s)')axs[0].set_xlabel('Shutter Speed (s)')# 使用分数表示快门速度axs[0].xaxis.set_major_formatter(ticker.FuncFormatter(lambda x, _: format_shutter_speed(x)))axs[0].set_ylabel('Frequency')axs[1].hist(focal_lengths, bins=100, color='red', edgecolor='black')axs[1].set_title('Focal Length Distribution')axs[1].set_xlabel('Focal Length (mm)')axs[1].set_ylabel('Frequency')plt.tight_layout()# 标出频率最高的N个焦距N = 6focal_length_counts = np.bincount(focal_lengths)most_common_focal_lengths = np.argsort(focal_length_counts)[-N:][::-1]for focal_length in most_common_focal_lengths:axs[1].text(focal_length, focal_length_counts[focal_length], str(focal_length), color='black')# 统计所有时间的频率dates_freq = Counter(dates)# 统计指定焦距的时间分布def get_focal_length_time_distribution(results, focal_length):date_of_focal_length = []for result in results:if result['focal_length'] and result['focal_length'].values[0].num / result['focal_length'].values[0].den == focal_length:date_of_focal_length.append(result['datetime'].values)date_of_focal_length.sort()# 以空格分隔时间字符串,只保留日期部分date_of_focal_length = [time.split(' ')[0].replace(':', '.') for time in date_of_focal_length]# 统计相同时间的频率return Counter(date_of_focal_length)prefix_focal_length = 50focal_length_200mm_freq = get_focal_length_time_distribution(results, prefix_focal_length)fig, ax = plt.subplots()# dates_freq排序dates_freq = dict(sorted(dates_freq.items()))ax.barh(list(dates_freq.keys()), list(dates_freq.values()), alpha=0.5, label='All')ax.barh(list(focal_length_200mm_freq.keys()), list(focal_length_200mm_freq.values()), label='Focal Length ' + str(prefix_focal_length) + 'mm')ax.legend()ax.set_xlabel('Frequency')ax.set_ylabel('Date')plt.show()

主函数

main函数设置文件夹路径,并调用process_images_in_folderplot_statistics函数。

def main():folder_path = 'c:/Users/25503/Desktop/照片合集'results = process_images_in_folder(folder_path)plot_statistics(results)if __name__ == "__main__":main()

运行结果

在这里插入图片描述
在这里插入图片描述

注意事项

  • 确保文件夹路径正确,并且文件夹中包含JPG格式的图片。
  • 脚本会读取图片的EXIF数据,如果图片没有EXIF数据,相关统计信息将无法获取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/148757.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

一张示意图看懂深度嵌入聚类DEC

深度嵌入聚类算法的架构。 步骤 1&#xff1a;根据输入数据集&#xff0c;训练自编码器将原始变量矩阵映射到潜在特征。 步骤 2&#xff1a;对潜在特征进行 K 均值聚类。 步骤 3-6&#xff1a;然后&#xff0c;为每个样本计算六个软标签&#xff0c;并估计目标分布&#xff…

小米机型更改参数与工程固件的关联 实例解析工程固件修改参数的步骤解析

工程固件写入后手机机型的端口默认是全开。包括usb调试以及基带端口diag 。而且工程固件基带默认是没有加密的。改写无限制。这也就是很多技术使用工程固件来写入机型的目的。今天简单来解析下工程固件修改参数的常规步骤以及一些常规知识。 通过博文了解: 1💝💝💝---…

基于vue框架的传染病人管理系统3w776(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;公告信息,工作人员,传染病人,上报记录,入住信息,需求订单,隔离结束记录 开题报告内容 基于Vue框架的传染病人管理系统开题报告 一、研究背景与意义 研究背景 在全球化的今天&#xff0c;人口流动日益频繁&#xff0c;传染病的传播速…

报文在VXLAN网络中是怎么转发的?这么简单居然有人不知道

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 你们好&#xff0c;我的网工朋友 不知道大家有没有想过这个问题&#xff1a;VXLAN网络中的报文是如何转发的&#xff1f; 在基本的二三层转发中…

在ComfyUI中,Cross-Attention优化方案应该选哪个?

&#x1f431;‍&#x1f409;背景 在comfyui中&#xff0c;如果你使用了秋叶的启动器&#xff0c;会在高级选项中看到这样一行选项&#xff1a;Cross-Attention优化方案&#xff0c;右边有个下拉框&#xff0c;可以选择的选项有4个&#xff0c;如下图&#xff1a; 那么&#…

vscode缩进 和自动格式化

如下图&#xff0c;缩进太大了。 检查2个地方 prettierrc.cjs文件。此处决定缩进几个tab vscode 的设置。 保存的时候 格式化。

计算机毕业设计 基于Python内蒙古旅游景点数据分析系统 Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

采购系统价格沉淀:降低采购成本,提高采购效率

在当今竞争激烈的市场环境中&#xff0c;企业对于成本控制与效率提升的追求从未停歇。采购作为企业运营的重要一环&#xff0c;其成本直接关联到产品的定价与市场竞争力。因此&#xff0c;引入并优化采购系统价格沉淀机制&#xff0c;成为众多企业降低采购成本、提升采购效率的…

在Windows系统上安装的 zstd C++ 库

在Windows系统上安装的 zstd C 库 项目地址:安装步骤步骤一步骤二 效果 项目地址: https://github.com/facebook/zstd 经过观察发现,这个项目没有CMakeLists.txt,只有Makefile,但是Makefile在windows系统下没有什么用, 所以说,常规的方式安装不可取了 安装步骤 步骤一 往下…

JAVA零基础入门——高级教程之集合框架

目录 1. 关于集合框架 1.1 集合接口 1.2 集合实现类 1.3 集合算法及迭代器和比较器的使用 2. 数据结构 2.1 ArrayList 2.2 LinkedList 2.3 HashMap 2.4 HashSet 3. 迭代器 1. 关于集合框架 集合框架是使用数据结构&#xff08;参见本文2. 数据结构&#xff09;来满…

传奇外网架设全套教程带图文解说——Gom引擎

想要自己架设传奇服务器&#xff0c;但没有技术怎么办&#xff1f; 1. 架设前的准备工作 ①通过百度网盘下载版本、补丁、客户端和DBC2000。版本解压到D盘&#xff0c;客户端解压到D盘或是E盘&#xff0c;补丁先不解压 ②安装和配置DBC2000&#xff0c;DBC2000数据库下载及安…

【Linux】Linux项目自动化构建工具--make和makefile

简单解释一下&#xff1a; make&#xff1a;一条命令&#xff1b; makefile/Makefile&#xff1a;一个文件&#xff1b; make/Makefile用法 因为makefile/Makefile本质就是一个文件&#xff0c;所以编辑这个文件就是&#xff1a; vim Makefile 下面让我们根据一个例子来学习ma…

C++ Primer Plus(速记版)-高级主题

第十七章 用于大型程序的工具 C 解决问题规模多样&#xff0c;对复杂问题尤其需用异常处理、命名空间和多重继承增强代码管理、库整合和概念表达&#xff0c;以适应大规模编程对错误处理、模块组合及高级功能设计的高要求。 17.1. 异常处理 异常处理允许C程序中不同部分通过抛…

聚铭下一代智慧安全运营中心荣获CNNVD兼容性资质证书

近日&#xff0c;聚铭网络旗下安全产品——聚铭下一代智慧安全运营中心正式通过了国家信息安全漏洞库&#xff08;CNNVD&#xff09;兼容性认证测试&#xff0c;荣获国家信息安全漏洞库兼容性资质证书。 关于CNNVD兼容性 国家信息安全漏洞库&#xff08;CNNVD&#xff09;是…

初始MYSQL数据库(6)—— 事务

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; MYSQL 目录 事务的概念 事务的ACID特性 使用事务 查看支持事务的存储引擎 事务的语法 保存点 自动/手动提交事务 事务的隔离性和…

微信小程序开发第七课

一 人脸识别 1.1 使用步骤 # 1 注册百度人脸识别接口 https://cloud.baidu.com/product/face.html # 2 免费领取额度&#xff1a;https://console.bce.baidu.com/ai/#/ai/face/overview/index# 3 创建应用&#xff1a;https://console.bce.baidu.com/ai/#/ai/face/app/list# …

【自动驾驶】控制算法(八)横向控制Ⅳ | 调试与优化——让车辆行驶更平稳!

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

iPhone锁屏密码忘了怎么解锁?轻松解锁攻略来了

在日常生活中&#xff0c;智能手机已成为我们不可或缺的伙伴。其中&#xff0c;iPhone以其出色的性能和优雅的设计&#xff0c;赢得了全球用户的喜爱。然而&#xff0c;即便是最忠实的iPhone用户&#xff0c;也可能会遇到一些棘手的问题&#xff0c;比如忘记了锁屏密码。面对这…

【高效且应用广泛的排序 —— 快速排序算法】

高效且应用广泛的排序 —— 快速排序算法 快速排序是一种常用的排序算法&#xff0c;主要采用分治的思想。以下是对快速排序算法的详细介绍及代码示例&#xff1a; 快速排序的基本思路是&#xff0c;每次将一个位置上的数据归位&#xff0c;使得该数左边的所有数据都比该数小…

工业物联网关为工业生产数字化转型赋能-天拓四方

一、引言 在工业4.0的大背景下&#xff0c;工业物联网关成为了制造业转型升级的关键技术之一。它通过连接设备和系统&#xff0c;实现数据的实时采集、处理和传输&#xff0c;从而提升生产效率、降低成本、优化资源配置&#xff0c;并最终推动整个制造业的数字化进程。本文将详…